Skip to content

Commit c8749b5

Browse files
bpo-46008: Make runtime-global object/type lifecycle functions and state consistent. (gh-29998)
This change is strictly renames and moving code around. It helps in the following ways: * ensures type-related init functions focus strictly on one of the three aspects (state, objects, types) * passes in PyInterpreterState * to all those functions, simplifying work on moving types/objects/state to the interpreter * consistent naming conventions help make what's going on more clear * keeping API related to a type in the corresponding header file makes it more obvious where to look for it https://bugs.python.org/issue46008
1 parent d8a464e commit c8749b5

38 files changed

+811
-354
lines changed

Include/internal/pycore_bytesobject.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef Py_INTERNAL_BYTESOBJECT_H
2+
#define Py_INTERNAL_BYTESOBJECT_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+
12+
/* runtime lifecycle */
13+
14+
extern PyStatus _PyBytes_InitGlobalObjects(PyInterpreterState *);
15+
extern PyStatus _PyBytes_InitTypes(PyInterpreterState *);
16+
extern void _PyBytes_Fini(PyInterpreterState *);
17+
18+
19+
/* other API */
20+
21+
struct _Py_bytes_state {
22+
PyObject *empty_string;
23+
PyBytesObject *characters[256];
24+
};
25+
26+
27+
#ifdef __cplusplus
28+
}
29+
#endif
30+
#endif /* !Py_INTERNAL_BYTESOBJECT_H */

Include/internal/pycore_context.h

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@
77

88
#include "pycore_hamt.h" /* PyHamtObject */
99

10+
11+
/* runtime lifecycle */
12+
13+
PyStatus _PyContext_InitTypes(PyInterpreterState *);
14+
void _PyContext_Fini(PyInterpreterState *);
15+
16+
17+
/* other API */
18+
19+
#ifndef WITH_FREELISTS
20+
// without freelists
21+
# define PyContext_MAXFREELIST 0
22+
#endif
23+
24+
#ifndef PyContext_MAXFREELIST
25+
# define PyContext_MAXFREELIST 255
26+
#endif
27+
28+
struct _Py_context_state {
29+
#if PyContext_MAXFREELIST > 0
30+
// List of free PyContext objects
31+
PyContext *freelist;
32+
int numfree;
33+
#endif
34+
};
35+
1036
struct _pycontextobject {
1137
PyObject_HEAD
1238
PyContext *ctx_prev;
@@ -36,7 +62,4 @@ struct _pycontexttokenobject {
3662
};
3763

3864

39-
int _PyContext_Init(void);
40-
void _PyContext_Fini(PyInterpreterState *interp);
41-
4265
#endif /* !Py_INTERNAL_CONTEXT_H */

Include/internal/pycore_dict.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,32 @@ extern "C" {
1010
#endif
1111

1212

13+
/* runtime lifecycle */
14+
15+
extern void _PyDict_Fini(PyInterpreterState *interp);
16+
17+
18+
/* other API */
19+
20+
#ifndef WITH_FREELISTS
21+
// without freelists
22+
# define PyDict_MAXFREELIST 0
23+
#endif
24+
25+
#ifndef PyDict_MAXFREELIST
26+
# define PyDict_MAXFREELIST 80
27+
#endif
28+
29+
struct _Py_dict_state {
30+
#if PyDict_MAXFREELIST > 0
31+
/* Dictionary reuse scheme to save calls to malloc and free */
32+
PyDictObject *free_list[PyDict_MAXFREELIST];
33+
int numfree;
34+
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
35+
int keys_numfree;
36+
#endif
37+
};
38+
1339
typedef struct {
1440
/* Cached hash code of me_key. */
1541
Py_hash_t me_hash;

Include/internal/pycore_exceptions.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef Py_INTERNAL_EXCEPTIONS_H
2+
#define Py_INTERNAL_EXCEPTIONS_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+
12+
/* runtime lifecycle */
13+
14+
extern PyStatus _PyExc_InitState(PyInterpreterState *);
15+
extern PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *);
16+
extern PyStatus _PyExc_InitTypes(PyInterpreterState *);
17+
extern void _PyExc_Fini(PyInterpreterState *);
18+
19+
20+
/* other API */
21+
22+
struct _Py_exc_state {
23+
// The dict mapping from errno codes to OSError subclasses
24+
PyObject *errnomap;
25+
PyBaseExceptionObject *memerrors_freelist;
26+
int memerrors_numfree;
27+
// The ExceptionGroup type
28+
PyObject *PyExc_ExceptionGroup;
29+
};
30+
31+
extern void _PyExc_ClearExceptionGroupType(PyInterpreterState *);
32+
33+
34+
#ifdef __cplusplus
35+
}
36+
#endif
37+
#endif /* !Py_INTERNAL_EXCEPTIONS_H */

Include/internal/pycore_floatobject.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,35 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
12+
/* runtime lifecycle */
13+
14+
extern void _PyFloat_InitState(PyInterpreterState *);
15+
extern PyStatus _PyFloat_InitTypes(PyInterpreterState *);
16+
extern void _PyFloat_Fini(PyInterpreterState *);
17+
18+
19+
/* other API */
20+
21+
#ifndef WITH_FREELISTS
22+
// without freelists
23+
# define PyFloat_MAXFREELIST 0
24+
#endif
25+
26+
#ifndef PyFloat_MAXFREELIST
27+
# define PyFloat_MAXFREELIST 100
28+
#endif
29+
30+
struct _Py_float_state {
31+
#if PyFloat_MAXFREELIST > 0
32+
/* Special free list
33+
free_list is a singly-linked list of available PyFloatObjects,
34+
linked via abuse of their ob_type members. */
35+
int numfree;
36+
PyFloatObject *free_list;
37+
#endif
38+
};
39+
1140
/* _PyFloat_{Pack,Unpack}{4,8}
1241
*
1342
* The struct and pickle (at least) modules need an efficient platform-

Include/internal/pycore_frame.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
extern "C" {
55
#endif
66

7+
8+
/* runtime lifecycle */
9+
10+
extern void _PyFrame_Fini(PyInterpreterState *interp);
11+
12+
13+
/* other API */
14+
715
/* These values are chosen so that the inline functions below all
816
* compare f_state to zero.
917
*/

Include/internal/pycore_genobject.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef Py_INTERNAL_GENOBJECT_H
2+
#define Py_INTERNAL_GENOBJECT_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+
12+
/* runtime lifecycle */
13+
14+
extern void _PyAsyncGen_Fini(PyInterpreterState *);
15+
16+
17+
/* other API */
18+
19+
#ifndef WITH_FREELISTS
20+
// without freelists
21+
# define _PyAsyncGen_MAXFREELIST 0
22+
#endif
23+
24+
#ifndef _PyAsyncGen_MAXFREELIST
25+
# define _PyAsyncGen_MAXFREELIST 80
26+
#endif
27+
28+
struct _Py_async_gen_state {
29+
#if _PyAsyncGen_MAXFREELIST > 0
30+
/* Freelists boost performance 6-10%; they also reduce memory
31+
fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
32+
are short-living objects that are instantiated for every
33+
__anext__() call. */
34+
struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST];
35+
int value_numfree;
36+
37+
struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST];
38+
int asend_numfree;
39+
#endif
40+
};
41+
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif
46+
#endif /* !Py_INTERNAL_GENOBJECT_H */

Include/internal/pycore_hamt.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
#define _Py_HAMT_MAX_TREE_DEPTH 7
99

1010

11+
/* runtime lifecycle */
12+
13+
PyStatus _PyHamt_InitTypes(PyInterpreterState *);
14+
void _PyHamt_Fini(PyInterpreterState *);
15+
16+
17+
/* other API */
18+
1119
#define PyHamt_Check(o) Py_IS_TYPE(o, &_PyHamt_Type)
1220

1321

@@ -110,7 +118,4 @@ PyObject * _PyHamt_NewIterValues(PyHamtObject *o);
110118
/* Return a Items iterator over "o". */
111119
PyObject * _PyHamt_NewIterItems(PyHamtObject *o);
112120

113-
int _PyHamt_Init(void);
114-
void _PyHamt_Fini(void);
115-
116121
#endif /* !Py_INTERNAL_HAMT_H */

0 commit comments

Comments
 (0)