Skip to content

Commit cdad272

Browse files
authored
bpo-40137: Add pycore_moduleobject.h internal header (pythonGH-25507)
Add pycore_moduleobject.h internal header file with static inline functions to access module members: * _PyModule_GetDict() * _PyModule_GetDef() * _PyModule_GetState() These functions don't check at runtime if their argument has a valid type and can be inlined even if Python is not built with LTO. _PyType_GetModuleByDef() uses _PyModule_GetDef(). Replace PyModule_GetState() with _PyModule_GetState() in the extension modules, considered as performance sensitive: * _abc * _functools * _operator * _pickle * _queue * _random * _sre * _struct * _thread * _winapi * array * posix The following extensions are now built with the Py_BUILD_CORE_MODULE macro defined, to be able to use the internal pycore_moduleobject.h header: _abc, array, _operator, _queue, _sre, _struct.
1 parent a32f8fe commit cdad272

21 files changed

+97
-47
lines changed
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef Py_INTERNAL_MODULEOBJECT_H
2+
#define Py_INTERNAL_MODULEOBJECT_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
typedef struct {
12+
PyObject_HEAD
13+
PyObject *md_dict;
14+
struct PyModuleDef *md_def;
15+
void *md_state;
16+
PyObject *md_weaklist;
17+
// for logging purposes after md_dict is cleared
18+
PyObject *md_name;
19+
} PyModuleObject;
20+
21+
static inline PyModuleDef* _PyModule_GetDef(PyObject *mod) {
22+
assert(PyModule_Check(mod));
23+
return ((PyModuleObject *)mod)->md_def;
24+
}
25+
26+
static inline void* _PyModule_GetState(PyObject* mod) {
27+
assert(PyModule_Check(mod));
28+
return ((PyModuleObject *)mod)->md_state;
29+
}
30+
31+
static inline PyObject* _PyModule_GetDict(PyObject *mod) {
32+
assert(PyModule_Check(mod));
33+
PyObject *dict = ((PyModuleObject *)mod) -> md_dict;
34+
// _PyModule_GetDict(mod) must not be used after calling module_clear(mod)
35+
assert(dict != NULL);
36+
return dict;
37+
}
38+
39+
#ifdef __cplusplus
40+
}
41+
#endif
42+
#endif /* !Py_INTERNAL_MODULEOBJECT_H */

Makefile.pre.in

+1
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,7 @@ PYTHON_HEADERS= \
11611161
$(srcdir)/Include/internal/pycore_interp.h \
11621162
$(srcdir)/Include/internal/pycore_list.h \
11631163
$(srcdir)/Include/internal/pycore_long.h \
1164+
$(srcdir)/Include/internal/pycore_moduleobject.h \
11641165
$(srcdir)/Include/internal/pycore_object.h \
11651166
$(srcdir)/Include/internal/pycore_pathconfig.h \
11661167
$(srcdir)/Include/internal/pycore_pyarena.h \

Modules/Setup

+6-6
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ posix -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal posixmodule.c # posix
105105
errno errnomodule.c # posix (UNIX) errno values
106106
pwd pwdmodule.c # this is needed to find out the user's home dir
107107
# if $HOME is not set
108-
_sre _sre.c # Fredrik Lundh's new regular expressions
108+
_sre -DPy_BUILD_CORE_BUILTIN _sre.c # Fredrik Lundh's new regular expressions
109109
_codecs _codecsmodule.c # access to the builtin codecs and codec registry
110110
_weakref _weakref.c # weak references
111111
_functools -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _functoolsmodule.c # Tools for working with functions and callable objects
112-
_operator _operator.c # operator.add() and similar goodies
112+
_operator -DPy_BUILD_CORE_BUILTIN _operator.c # operator.add() and similar goodies
113113
_collections _collectionsmodule.c # Container types
114-
_abc _abc.c # Abstract base classes
114+
_abc -DPy_BUILD_CORE_BUILTIN _abc.c # Abstract base classes
115115
itertools itertoolsmodule.c # Functions creating iterators for efficient looping
116116
atexit atexitmodule.c # Register functions to be run at interpreter-shutdown
117117
_signal -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal signalmodule.c
@@ -166,17 +166,17 @@ _symtable symtablemodule.c
166166

167167
# Modules that should always be present (non UNIX dependent):
168168

169-
#array arraymodule.c # array objects
169+
#array -DPy_BUILD_CORE_MODULE arraymodule.c # array objects
170170
#cmath cmathmodule.c _math.c -DPy_BUILD_CORE_MODULE # -lm # complex math library functions
171171
#math mathmodule.c _math.c -DPy_BUILD_CORE_MODULE # -lm # math library functions, e.g. sin()
172172
#_contextvars _contextvarsmodule.c # Context Variables
173-
#_struct _struct.c # binary structure packing/unpacking
173+
#_struct -DPy_BUILD_CORE_MODULE _struct.c # binary structure packing/unpacking
174174
#_weakref _weakref.c # basic weak reference support
175175
#_testcapi _testcapimodule.c # Python C API test module
176176
#_testinternalcapi _testinternalcapi.c -I$(srcdir)/Include/internal -DPy_BUILD_CORE_MODULE # Python internal C API test module
177177
#_random _randommodule.c -DPy_BUILD_CORE_MODULE # Random number generator
178178
#_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator
179-
#_pickle _pickle.c # pickle accelerator
179+
#_pickle -DPy_BUILD_CORE_MODULE _pickle.c # pickle accelerator
180180
#_datetime _datetimemodule.c # datetime accelerator
181181
#_zoneinfo _zoneinfo.c -DPy_BUILD_CORE_MODULE # zoneinfo accelerator
182182
#_bisect _bisectmodule.c # Bisection algorithms

Modules/_abc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* ABCMeta implementation */
22

33
#include "Python.h"
4+
#include "pycore_moduleobject.h" // _PyModule_GetState()
45
#include "clinic/_abc.c.h"
56

67
/*[clinic input]
@@ -27,7 +28,7 @@ typedef struct {
2728
static inline _abcmodule_state*
2829
get_abc_state(PyObject *module)
2930
{
30-
void *state = PyModule_GetState(module);
31+
void *state = _PyModule_GetState(module);
3132
assert(state != NULL);
3233
return (_abcmodule_state *)state;
3334
}

Modules/_functoolsmodule.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Python.h"
22
#include "pycore_long.h" // _PyLong_GetZero()
3+
#include "pycore_moduleobject.h" // _PyModule_GetState()
34
#include "pycore_object.h" // _PyObject_GC_TRACK
45
#include "pycore_pystate.h" // _PyThreadState_GET()
56
#include "pycore_tuple.h" // _PyTuple_ITEMS()
@@ -23,7 +24,7 @@ typedef struct _functools_state {
2324
static inline _functools_state *
2425
get_functools_state(PyObject *module)
2526
{
26-
void *state = PyModule_GetState(module);
27+
void *state = _PyModule_GetState(module);
2728
assert(state != NULL);
2829
return (_functools_state *)state;
2930
}
@@ -53,8 +54,7 @@ get_functools_state_by_type(PyTypeObject *type)
5354
if (module == NULL) {
5455
return NULL;
5556
}
56-
_functools_state *state = get_functools_state(module);
57-
return state;
57+
return get_functools_state(module);
5858
}
5959

6060
static PyObject *

Modules/_operator.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
21
#include "Python.h"
3-
2+
#include "pycore_moduleobject.h" // _PyModule_GetState()
43
#include "clinic/_operator.c.h"
54

65
typedef struct {
@@ -12,7 +11,7 @@ typedef struct {
1211
static inline _operator_state*
1312
get_operator_state(PyObject *module)
1413
{
15-
void *state = PyModule_GetState(module);
14+
void *state = _PyModule_GetState(module);
1615
assert(state != NULL);
1716
return (_operator_state *)state;
1817
}

Modules/_pickle.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#endif
1010

1111
#include "Python.h"
12+
#include "pycore_moduleobject.h" // _PyModule_GetState()
1213
#include "structmember.h" // PyMemberDef
1314

1415
PyDoc_STRVAR(pickle_module_doc,
@@ -182,7 +183,7 @@ static struct PyModuleDef _picklemodule;
182183
static PickleState *
183184
_Pickle_GetState(PyObject *module)
184185
{
185-
return (PickleState *)PyModule_GetState(module);
186+
return (PickleState *)_PyModule_GetState(module);
186187
}
187188

188189
/* Find the module instance imported in the currently running sub-interpreter

Modules/_queuemodule.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "Python.h"
2+
#include "pycore_moduleobject.h" // _PyModule_GetState()
23
#include "structmember.h" // PyMemberDef
34
#include <stddef.h> // offsetof()
45

@@ -10,7 +11,7 @@ typedef struct {
1011
static simplequeue_state *
1112
simplequeue_get_state(PyObject *module)
1213
{
13-
simplequeue_state *state = PyModule_GetState(module);
14+
simplequeue_state *state = _PyModule_GetState(module);
1415
assert(state);
1516
return state;
1617
}

Modules/_randommodule.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
/* ---------------------------------------------------------------*/
6868

6969
#include "Python.h"
70+
#include "pycore_moduleobject.h" // _PyModule_GetState()
7071
#ifdef HAVE_PROCESS_H
7172
# include <process.h> // getpid()
7273
#endif
@@ -86,7 +87,7 @@ typedef struct {
8687
static inline _randomstate*
8788
get_random_state(PyObject *module)
8889
{
89-
void *state = PyModule_GetState(module);
90+
void *state = _PyModule_GetState(module);
9091
assert(state != NULL);
9192
return (_randomstate *)state;
9293
}
@@ -538,7 +539,7 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
538539

539540
if (PyTuple_GET_SIZE(args) == 1)
540541
arg = PyTuple_GET_ITEM(args, 0);
541-
542+
542543
tmp = random_seed(self, arg);
543544
if (tmp == NULL) {
544545
Py_DECREF(self);

Modules/_sre.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static const char copyright[] =
4242

4343
#include "Python.h"
4444
#include "pycore_long.h" // _PyLong_GetZero()
45+
#include "pycore_moduleobject.h" // _PyModule_GetState()
4546
#include "structmember.h" // PyMemberDef
4647

4748
#include "sre.h"
@@ -258,7 +259,7 @@ typedef struct {
258259
static _sremodulestate *
259260
get_sre_module_state(PyObject *m)
260261
{
261-
_sremodulestate *state = (_sremodulestate *)PyModule_GetState(m);
262+
_sremodulestate *state = (_sremodulestate *)_PyModule_GetState(m);
262263
assert(state);
263264
return state;
264265
}

Modules/_struct.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define PY_SSIZE_T_CLEAN
77

88
#include "Python.h"
9+
#include "pycore_moduleobject.h" // _PyModule_GetState()
910
#include "structmember.h" // PyMemberDef
1011
#include <ctype.h>
1112

@@ -24,7 +25,7 @@ typedef struct {
2425
static inline _structmodulestate*
2526
get_struct_state(PyObject *module)
2627
{
27-
void *state = PyModule_GetState(module);
28+
void *state = _PyModule_GetState(module);
2829
assert(state != NULL);
2930
return (_structmodulestate *)state;
3031
}

Modules/_threadmodule.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
/* Interface to Sjoerd's portable C thread library */
44

55
#include "Python.h"
6-
#include "pycore_pylifecycle.h"
76
#include "pycore_interp.h" // _PyInterpreterState.num_threads
7+
#include "pycore_moduleobject.h" // _PyModule_GetState()
8+
#include "pycore_pylifecycle.h"
89
#include "pycore_pystate.h" // _PyThreadState_Init()
910
#include <stddef.h> // offsetof()
1011
#include "structmember.h" // PyMemberDef
@@ -35,7 +36,7 @@ typedef struct {
3536
static inline thread_module_state*
3637
get_thread_state(PyObject *module)
3738
{
38-
void *state = PyModule_GetState(module);
39+
void *state = _PyModule_GetState(module);
3940
assert(state != NULL);
4041
return (thread_module_state *)state;
4142
}

Modules/_winapi.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
/* See http://www.python.org/2.4/license for licensing details. */
3636

3737
#include "Python.h"
38-
#include "moduleobject.h" // PyModuleDef_Slot
38+
#include "pycore_moduleobject.h" // _PyModule_GetState()
3939
#include "structmember.h" // PyMemberDef
4040

4141

@@ -87,7 +87,7 @@ typedef struct {
8787
static inline WinApiState*
8888
winapi_get_state(PyObject *module)
8989
{
90-
void *state = PyModule_GetState(module);
90+
void *state = _PyModule_GetState(module);
9191
assert(state != NULL);
9292
return (WinApiState *)state;
9393
}

Modules/arraymodule.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#define PY_SSIZE_T_CLEAN
77
#include "Python.h"
8+
#include "pycore_moduleobject.h" // _PyModule_GetState()
89
#include "structmember.h" // PyMemberDef
910
#include <stddef.h> // offsetof()
1011

@@ -63,7 +64,7 @@ typedef struct {
6364
static array_state *
6465
get_array_state(PyObject *module)
6566
{
66-
return (array_state *)PyModule_GetState(module);
67+
return (array_state *)_PyModule_GetState(module);
6768
}
6869

6970
#define find_array_state_by_type(tp) \

Modules/posixmodule.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "Python.h"
1313
#include "pycore_fileutils.h"
14+
#include "pycore_moduleobject.h" // _PyModule_GetState()
1415
#ifdef MS_WINDOWS
1516
/* include <windows.h> early to avoid conflict with pycore_condvar.h:
1617
@@ -994,7 +995,7 @@ typedef struct {
994995
static inline _posixstate*
995996
get_posix_state(PyObject *module)
996997
{
997-
void *state = PyModule_GetState(module);
998+
void *state = _PyModule_GetState(module);
998999
assert(state != NULL);
9991000
return (_posixstate *)state;
10001001
}

Objects/frameobject.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Python.h"
44
#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals()
5+
#include "pycore_moduleobject.h" // _PyModule_GetDict()
56
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
67

78
#include "frameobject.h" // PyFrameObject
@@ -1176,7 +1177,7 @@ _PyEval_BuiltinsFromGlobals(PyThreadState *tstate, PyObject *globals)
11761177
PyObject *builtins = _PyDict_GetItemIdWithError(globals, &PyId___builtins__);
11771178
if (builtins) {
11781179
if (PyModule_Check(builtins)) {
1179-
builtins = PyModule_GetDict(builtins);
1180+
builtins = _PyModule_GetDict(builtins);
11801181
assert(builtins != NULL);
11811182
}
11821183
return builtins;

Objects/moduleobject.c

+4-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Python.h"
55
#include "pycore_interp.h" // PyInterpreterState.importlib
66
#include "pycore_pystate.h" // _PyInterpreterState_GET()
7+
#include "pycore_moduleobject.h" // _PyModule_GetDef()
78
#include "structmember.h" // PyMemberDef
89

910
static Py_ssize_t max_module_number;
@@ -12,15 +13,6 @@ _Py_IDENTIFIER(__doc__);
1213
_Py_IDENTIFIER(__name__);
1314
_Py_IDENTIFIER(__spec__);
1415

15-
typedef struct {
16-
PyObject_HEAD
17-
PyObject *md_dict;
18-
struct PyModuleDef *md_def;
19-
void *md_state;
20-
PyObject *md_weaklist;
21-
PyObject *md_name; /* for logging purposes after md_dict is cleared */
22-
} PyModuleObject;
23-
2416
static PyMemberDef module_members[] = {
2517
{"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
2618
{0}
@@ -469,14 +461,11 @@ PyModule_SetDocString(PyObject *m, const char *doc)
469461
PyObject *
470462
PyModule_GetDict(PyObject *m)
471463
{
472-
PyObject *d;
473464
if (!PyModule_Check(m)) {
474465
PyErr_BadInternalCall();
475466
return NULL;
476467
}
477-
d = ((PyModuleObject *)m) -> md_dict;
478-
assert(d != NULL);
479-
return d;
468+
return _PyModule_GetDict(m);
480469
}
481470

482471
PyObject*
@@ -556,7 +545,7 @@ PyModule_GetDef(PyObject* m)
556545
PyErr_BadArgument();
557546
return NULL;
558547
}
559-
return ((PyModuleObject *)m)->md_def;
548+
return _PyModule_GetDef(m);
560549
}
561550

562551
void*
@@ -566,7 +555,7 @@ PyModule_GetState(PyObject* m)
566555
PyErr_BadArgument();
567556
return NULL;
568557
}
569-
return ((PyModuleObject *)m)->md_state;
558+
return _PyModule_GetState(m);
570559
}
571560

572561
void

0 commit comments

Comments
 (0)