From 877c5f933fcd77455e5b393157e4777434d199b3 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 11 Nov 2022 12:36:41 -0700 Subject: [PATCH 1/4] Pass the interpreter to _PyStaticObjects_CheckRefcnt(). --- Python/pylifecycle.c | 2 +- Tools/build/generate_global_objects.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 13519762fa87bf..3991089b38c451 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1744,7 +1744,7 @@ finalize_interp_types(PyInterpreterState *interp) _PyUnicode_Fini(interp); _PyFloat_Fini(interp); #ifdef Py_DEBUG - _PyStaticObjects_CheckRefcnt(); + _PyStaticObjects_CheckRefcnt(interp); #endif } diff --git a/Tools/build/generate_global_objects.py b/Tools/build/generate_global_objects.py index 815045c27c1892..b4243273ff4f6c 100644 --- a/Tools/build/generate_global_objects.py +++ b/Tools/build/generate_global_objects.py @@ -383,8 +383,10 @@ def generate_global_object_finalizers(generated_immortal_objects): printer.write(START) printer.write('#ifdef Py_DEBUG') printer.write("static inline void") - with printer.block("_PyStaticObjects_CheckRefcnt(void)"): - printer.write('/* generated (see pycore_runtime_init_generated.h) */') + with printer.block( + "_PyStaticObjects_CheckRefcnt(PyInterpreterState *interp)"): + printer.write('/* generated runtime-global */') + printer.write('// (see pycore_runtime_init_generated.h)') for ref in generated_immortal_objects: printer.write(f'_PyStaticObject_CheckRefcnt({ref});') printer.write('/* non-generated */') From c923a40ebc1f97f449350c6d69d5888fc3923487 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 11 Nov 2022 12:39:45 -0700 Subject: [PATCH 2/4] Add PyInterpreterState.static_objects. --- Include/internal/pycore_global_objects.h | 11 +++++++++++ .../internal/pycore_global_objects_fini_generated.h | 5 +++-- Include/internal/pycore_interp.h | 3 +++ Include/internal/pycore_runtime_init.h | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 82e89db7b1b750..4050d6d543b320 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -49,6 +49,17 @@ struct _Py_global_objects { PyObject *interned; }; +#define _Py_INTERP_OBJECT(interp, NAME) \ + (interp)->static_objects.NAME +#define _Py_INTERP_SINGLETON(interp, NAME) \ + _Py_INTERP_OBJECT(interp, singletons.NAME) + +struct _Py_interp_static_objects { + struct { + int _not_used; + } singletons; +}; + #ifdef __cplusplus } diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 7bf31841ff5dad..59001dc950925b 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -24,8 +24,9 @@ _PyStaticObject_CheckRefcnt(PyObject *obj) { /* The following is auto-generated by Tools/build/generate_global_objects.py. */ #ifdef Py_DEBUG static inline void -_PyStaticObjects_CheckRefcnt(void) { - /* generated (see pycore_runtime_init_generated.h) */ +_PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { + /* generated runtime-global */ + // (see pycore_runtime_init_generated.h) _PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -5]); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -4]); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -3]); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index ae2a3d3b13cfa9..61d32e6b13d570 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -20,6 +20,7 @@ extern "C" { #include "pycore_genobject.h" // struct _Py_async_gen_state #include "pycore_gc.h" // struct _gc_runtime_state #include "pycore_list.h" // struct _Py_list_state +#include "pycore_global_objects.h" // struct _Py_interp_static_objects #include "pycore_tuple.h" // struct _Py_tuple_state #include "pycore_typeobject.h" // struct type_cache #include "pycore_unicodeobject.h" // struct _Py_unicode_state @@ -188,6 +189,8 @@ struct _is { struct callable_cache callable_cache; PyCodeObject *interpreter_trampoline; + struct _Py_interp_static_objects static_objects; + /* The following fields are here to avoid allocation during init. The data is exposed through PyInterpreterState pointer fields. These fields should not be accessed directly outside of init. diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 4e8dd7b8a0fb5a..41a7730490abe9 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -77,6 +77,11 @@ extern "C" { { .threshold = 10, }, \ }, \ }, \ + .static_objects = { \ + .singletons = { \ + ._not_used = 1, \ + }, \ + }, \ ._initial_thread = _PyThreadState_INIT, \ } From 560590a7586cc4353067bd4eff5211bc7a9e8472 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 11 Nov 2022 13:45:27 -0700 Subject: [PATCH 3/4] _Py_INTERP_OBJECT() -> _Py_INTERP_STATIC_OBJECT() --- Include/internal/pycore_global_objects.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 4050d6d543b320..1f9b57c4b14953 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -49,10 +49,10 @@ struct _Py_global_objects { PyObject *interned; }; -#define _Py_INTERP_OBJECT(interp, NAME) \ +#define _Py_INTERP_STATIC_OBJECT(interp, NAME) \ (interp)->static_objects.NAME #define _Py_INTERP_SINGLETON(interp, NAME) \ - _Py_INTERP_OBJECT(interp, singletons.NAME) + _Py_INTERP_STATIC_OBJECT(interp, singletons.NAME) struct _Py_interp_static_objects { struct { From 65532f63e195efc025491572a066db9757139194 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 11 Nov 2022 13:49:02 -0700 Subject: [PATCH 4/4] Add PyInterpreterState.cached_objects. --- Include/internal/pycore_global_objects.h | 7 +++++++ Include/internal/pycore_interp.h | 1 + 2 files changed, 8 insertions(+) diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 1f9b57c4b14953..3561f686a0de5c 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -49,6 +49,13 @@ struct _Py_global_objects { PyObject *interned; }; +#define _Py_INTERP_CACHED_OBJECT(interp, NAME) \ + (interp)->cached_objects.NAME + +struct _Py_interp_cached_objects { + int _not_set; +}; + #define _Py_INTERP_STATIC_OBJECT(interp, NAME) \ (interp)->static_objects.NAME #define _Py_INTERP_SINGLETON(interp, NAME) \ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 61d32e6b13d570..735523c9c4f1ec 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -189,6 +189,7 @@ struct _is { struct callable_cache callable_cache; PyCodeObject *interpreter_trampoline; + struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; /* The following fields are here to avoid allocation during init.