gh-140550: Use a bool for the Py_mod_gil value (GH-141519)

This needs a single bit, but was stored as a void* in the module
struct. This didn't matter due to packing, but now that there's
another bool in the struct, we can save a bit of memory by
making md_gil a bool.

Variables that changed type are renamed, to detect conflicts.
This commit is contained in:
Petr Viktorin 2025-11-14 10:38:49 +01:00 committed by GitHub
parent 4885ecfbda
commit a4dd66275b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 24 additions and 21 deletions

View file

@ -30,7 +30,7 @@ typedef struct {
PyObject *md_name; PyObject *md_name;
bool md_token_is_def; /* if true, `md_token` is the PyModuleDef */ bool md_token_is_def; /* if true, `md_token` is the PyModuleDef */
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
void *md_gil; bool md_requires_gil;
#endif #endif
Py_ssize_t md_state_size; Py_ssize_t md_state_size;
traverseproc md_state_traverse; traverseproc md_state_traverse;

View file

@ -1725,7 +1725,7 @@ def get_gen(): yield 1
check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit) check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit)
# module # module
if support.Py_GIL_DISABLED: if support.Py_GIL_DISABLED:
md_gil = 'P' md_gil = '?'
else: else:
md_gil = '' md_gil = ''
check(unittest, size('PPPP?' + md_gil + 'NPPPPP')) check(unittest, size('PPPP?' + md_gil + 'NPPPPP'))

View file

@ -178,7 +178,7 @@ new_module_notrack(PyTypeObject *mt)
m->md_name = NULL; m->md_name = NULL;
m->md_token_is_def = false; m->md_token_is_def = false;
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
m->md_gil = Py_MOD_GIL_USED; m->md_requires_gil = true;
#endif #endif
m->md_state_size = 0; m->md_state_size = 0;
m->md_state_traverse = NULL; m->md_state_traverse = NULL;
@ -361,7 +361,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
m->md_token_is_def = true; m->md_token_is_def = true;
module_copy_members_from_deflike(m, module); module_copy_members_from_deflike(m, module);
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
m->md_gil = Py_MOD_GIL_USED; m->md_requires_gil = true;
#endif #endif
return (PyObject*)m; return (PyObject*)m;
} }
@ -380,7 +380,7 @@ module_from_def_and_spec(
int has_multiple_interpreters_slot = 0; int has_multiple_interpreters_slot = 0;
void *multiple_interpreters = (void *)0; void *multiple_interpreters = (void *)0;
int has_gil_slot = 0; int has_gil_slot = 0;
void *gil_slot = Py_MOD_GIL_USED; bool requires_gil = true;
int has_execution_slots = 0; int has_execution_slots = 0;
const char *name; const char *name;
int ret; int ret;
@ -474,7 +474,7 @@ module_from_def_and_spec(
name); name);
goto error; goto error;
} }
gil_slot = cur_slot->value; requires_gil = (cur_slot->value != Py_MOD_GIL_NOT_USED);
has_gil_slot = 1; has_gil_slot = 1;
break; break;
case Py_mod_abi: case Py_mod_abi:
@ -581,9 +581,9 @@ module_from_def_and_spec(
mod->md_token = token; mod->md_token = token;
} }
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
mod->md_gil = gil_slot; mod->md_requires_gil = requires_gil;
#else #else
(void)gil_slot; (void)requires_gil;
#endif #endif
mod->md_exec = m_exec; mod->md_exec = m_exec;
} else { } else {
@ -664,11 +664,12 @@ PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *slots, PyObject *spec)
int int
PyUnstable_Module_SetGIL(PyObject *module, void *gil) PyUnstable_Module_SetGIL(PyObject *module, void *gil)
{ {
bool requires_gil = (gil != Py_MOD_GIL_NOT_USED);
if (!PyModule_Check(module)) { if (!PyModule_Check(module)) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
} }
((PyModuleObject *)module)->md_gil = gil; ((PyModuleObject *)module)->md_requires_gil = requires_gil;
return 0; return 0;
} }
#endif #endif

View file

@ -1017,9 +1017,10 @@ struct extensions_cache_value {
_Py_ext_module_origin origin; _Py_ext_module_origin origin;
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
/* The module's md_gil slot, for legacy modules that are reinitialized from /* The module's md_requires_gil member, for legacy modules that are
m_dict rather than calling their initialization function again. */ * reinitialized from m_dict rather than calling their initialization
void *md_gil; * function again. */
bool md_requires_gil;
#endif #endif
}; };
@ -1350,7 +1351,7 @@ static struct extensions_cache_value *
_extensions_cache_set(PyObject *path, PyObject *name, _extensions_cache_set(PyObject *path, PyObject *name,
PyModuleDef *def, PyModInitFunction m_init, PyModuleDef *def, PyModInitFunction m_init,
Py_ssize_t m_index, PyObject *m_dict, Py_ssize_t m_index, PyObject *m_dict,
_Py_ext_module_origin origin, void *md_gil) _Py_ext_module_origin origin, bool requires_gil)
{ {
struct extensions_cache_value *value = NULL; struct extensions_cache_value *value = NULL;
void *key = NULL; void *key = NULL;
@ -1405,11 +1406,11 @@ _extensions_cache_set(PyObject *path, PyObject *name,
/* m_dict is set by set_cached_m_dict(). */ /* m_dict is set by set_cached_m_dict(). */
.origin=origin, .origin=origin,
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
.md_gil=md_gil, .md_requires_gil=requires_gil,
#endif #endif
}; };
#ifndef Py_GIL_DISABLED #ifndef Py_GIL_DISABLED
(void)md_gil; (void)requires_gil;
#endif #endif
if (init_cached_m_dict(newvalue, m_dict) < 0) { if (init_cached_m_dict(newvalue, m_dict) < 0) {
goto finally; goto finally;
@ -1547,7 +1548,8 @@ _PyImport_CheckGILForModule(PyObject* module, PyObject *module_name)
} }
if (!PyModule_Check(module) || if (!PyModule_Check(module) ||
((PyModuleObject *)module)->md_gil == Py_MOD_GIL_USED) { ((PyModuleObject *)module)->md_requires_gil)
{
if (_PyEval_EnableGILPermanent(tstate)) { if (_PyEval_EnableGILPermanent(tstate)) {
int warn_result = PyErr_WarnFormat( int warn_result = PyErr_WarnFormat(
PyExc_RuntimeWarning, PyExc_RuntimeWarning,
@ -1725,7 +1727,7 @@ struct singlephase_global_update {
Py_ssize_t m_index; Py_ssize_t m_index;
PyObject *m_dict; PyObject *m_dict;
_Py_ext_module_origin origin; _Py_ext_module_origin origin;
void *md_gil; bool md_requires_gil;
}; };
static struct extensions_cache_value * static struct extensions_cache_value *
@ -1784,7 +1786,7 @@ update_global_state_for_extension(PyThreadState *tstate,
#endif #endif
cached = _extensions_cache_set( cached = _extensions_cache_set(
path, name, def, m_init, singlephase->m_index, m_dict, path, name, def, m_init, singlephase->m_index, m_dict,
singlephase->origin, singlephase->md_gil); singlephase->origin, singlephase->md_requires_gil);
if (cached == NULL) { if (cached == NULL) {
// XXX Ignore this error? Doing so would effectively // XXX Ignore this error? Doing so would effectively
// mark the module as not loadable. // mark the module as not loadable.
@ -1873,7 +1875,7 @@ reload_singlephase_extension(PyThreadState *tstate,
if (def->m_base.m_copy != NULL) { if (def->m_base.m_copy != NULL) {
// For non-core modules, fetch the GIL slot that was stored by // For non-core modules, fetch the GIL slot that was stored by
// import_run_extension(). // import_run_extension().
((PyModuleObject *)mod)->md_gil = cached->md_gil; ((PyModuleObject *)mod)->md_requires_gil = cached->md_requires_gil;
} }
#endif #endif
/* We can't set mod->md_def if it's missing, /* We can't set mod->md_def if it's missing,
@ -2128,7 +2130,7 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
.m_index=def->m_base.m_index, .m_index=def->m_base.m_index,
.origin=info->origin, .origin=info->origin,
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
.md_gil=((PyModuleObject *)mod)->md_gil, .md_requires_gil=((PyModuleObject *)mod)->md_requires_gil,
#endif #endif
}; };
// gh-88216: Extensions and def->m_base.m_copy can be updated // gh-88216: Extensions and def->m_base.m_copy can be updated
@ -2323,7 +2325,7 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name,
.origin=_Py_ext_module_origin_CORE, .origin=_Py_ext_module_origin_CORE,
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
/* Unused when m_dict == NULL. */ /* Unused when m_dict == NULL. */
.md_gil=NULL, .md_requires_gil=false,
#endif #endif
}; };
cached = update_global_state_for_extension( cached = update_global_state_for_extension(