mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-81057: Move contextvars-related Globals to _PyRuntimeState (gh-99400)
This is part of the effort to consolidate global variables, to make them easier to manage (and make it easier to later move some of them to PyInterpreterState). https://github.com/python/cpython/issues/81057
This commit is contained in:
parent
5f55067e23
commit
01fa907aa8
9 changed files with 82 additions and 90 deletions
|
@ -18,6 +18,10 @@ void _PyContext_Fini(PyInterpreterState *);
|
||||||
|
|
||||||
/* other API */
|
/* other API */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
} _PyContextTokenMissing;
|
||||||
|
|
||||||
#ifndef WITH_FREELISTS
|
#ifndef WITH_FREELISTS
|
||||||
// without freelists
|
// without freelists
|
||||||
# define PyContext_MAXFREELIST 0
|
# define PyContext_MAXFREELIST 0
|
||||||
|
|
|
@ -10,6 +10,8 @@ extern "C" {
|
||||||
|
|
||||||
#include "pycore_gc.h" // PyGC_Head
|
#include "pycore_gc.h" // PyGC_Head
|
||||||
#include "pycore_global_strings.h" // struct _Py_global_strings
|
#include "pycore_global_strings.h" // struct _Py_global_strings
|
||||||
|
#include "pycore_hamt.h" // PyHamtNode_Bitmap
|
||||||
|
#include "pycore_context.h" // _PyContextTokenMissing
|
||||||
#include "pycore_typeobject.h" // pytype_slotdef
|
#include "pycore_typeobject.h" // pytype_slotdef
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,6 +54,10 @@ struct _Py_global_objects {
|
||||||
|
|
||||||
_PyGC_Head_UNUSED _tuple_empty_gc_not_used;
|
_PyGC_Head_UNUSED _tuple_empty_gc_not_used;
|
||||||
PyTupleObject tuple_empty;
|
PyTupleObject tuple_empty;
|
||||||
|
|
||||||
|
_PyGC_Head_UNUSED _hamt_bitmap_node_empty_gc_not_used;
|
||||||
|
PyHamtNode_Bitmap hamt_bitmap_node_empty;
|
||||||
|
_PyContextTokenMissing context_token_missing;
|
||||||
} singletons;
|
} singletons;
|
||||||
|
|
||||||
PyObject *interned;
|
PyObject *interned;
|
||||||
|
@ -76,6 +82,9 @@ struct _Py_interp_cached_objects {
|
||||||
struct _Py_interp_static_objects {
|
struct _Py_interp_static_objects {
|
||||||
struct {
|
struct {
|
||||||
int _not_used;
|
int _not_used;
|
||||||
|
// hamt_empty is here instead of global because of its weakreflist.
|
||||||
|
_PyGC_Head_UNUSED _hamt_empty_gc_not_used;
|
||||||
|
PyHamtObject hamt_empty;
|
||||||
} singletons;
|
} singletons;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1475,6 +1475,9 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
/* non-generated */
|
/* non-generated */
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(bytes_empty));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(bytes_empty));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(tuple_empty));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(tuple_empty));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(hamt_bitmap_node_empty));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_INTERP_SINGLETON(interp, hamt_empty));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_SINGLETON(context_token_missing));
|
||||||
}
|
}
|
||||||
#endif // Py_DEBUG
|
#endif // Py_DEBUG
|
||||||
/* End auto-generated code */
|
/* End auto-generated code */
|
||||||
|
|
|
@ -28,10 +28,6 @@ extern PyTypeObject _PyHamtKeys_Type;
|
||||||
extern PyTypeObject _PyHamtValues_Type;
|
extern PyTypeObject _PyHamtValues_Type;
|
||||||
extern PyTypeObject _PyHamtItems_Type;
|
extern PyTypeObject _PyHamtItems_Type;
|
||||||
|
|
||||||
/* runtime lifecycle */
|
|
||||||
|
|
||||||
void _PyHamt_Fini(PyInterpreterState *);
|
|
||||||
|
|
||||||
|
|
||||||
/* other API */
|
/* other API */
|
||||||
|
|
||||||
|
@ -53,6 +49,13 @@ typedef struct {
|
||||||
} PyHamtObject;
|
} PyHamtObject;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_VAR_HEAD
|
||||||
|
uint32_t b_bitmap;
|
||||||
|
PyObject *b_array[1];
|
||||||
|
} PyHamtNode_Bitmap;
|
||||||
|
|
||||||
|
|
||||||
/* A struct to hold the state of depth-first traverse of the tree.
|
/* A struct to hold the state of depth-first traverse of the tree.
|
||||||
|
|
||||||
HAMT is an immutable collection. Iterators will hold a strong reference
|
HAMT is an immutable collection. Iterators will hold a strong reference
|
||||||
|
|
|
@ -75,6 +75,12 @@ extern "C" {
|
||||||
.tuple_empty = { \
|
.tuple_empty = { \
|
||||||
.ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0) \
|
.ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0) \
|
||||||
}, \
|
}, \
|
||||||
|
.hamt_bitmap_node_empty = { \
|
||||||
|
.ob_base = _PyVarObject_IMMORTAL_INIT(&_PyHamt_BitmapNode_Type, 0) \
|
||||||
|
}, \
|
||||||
|
.context_token_missing = { \
|
||||||
|
.ob_base = _PyObject_IMMORTAL_INIT(&_PyContextTokenMissing_Type), \
|
||||||
|
}, \
|
||||||
}, \
|
}, \
|
||||||
}, \
|
}, \
|
||||||
._main_interpreter = _PyInterpreterState_INIT, \
|
._main_interpreter = _PyInterpreterState_INIT, \
|
||||||
|
@ -112,6 +118,10 @@ extern "C" {
|
||||||
.static_objects = { \
|
.static_objects = { \
|
||||||
.singletons = { \
|
.singletons = { \
|
||||||
._not_used = 1, \
|
._not_used = 1, \
|
||||||
|
.hamt_empty = { \
|
||||||
|
.ob_base = _PyObject_IMMORTAL_INIT(&_PyHamt_Type), \
|
||||||
|
.h_root = (PyHamtNode*)&_Py_SINGLETON(hamt_bitmap_node_empty), \
|
||||||
|
}, \
|
||||||
}, \
|
}, \
|
||||||
}, \
|
}, \
|
||||||
._initial_thread = _PyThreadState_INIT, \
|
._initial_thread = _PyThreadState_INIT, \
|
||||||
|
|
|
@ -1235,25 +1235,29 @@ token_new(PyContext *ctx, PyContextVar *var, PyObject *val)
|
||||||
/////////////////////////// Token.MISSING
|
/////////////////////////// Token.MISSING
|
||||||
|
|
||||||
|
|
||||||
static PyObject *_token_missing;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
} PyContextTokenMissing;
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
context_token_missing_tp_repr(PyObject *self)
|
context_token_missing_tp_repr(PyObject *self)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString("<Token.MISSING>");
|
return PyUnicode_FromString("<Token.MISSING>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
context_token_missing_tp_dealloc(_PyContextTokenMissing *Py_UNUSED(self))
|
||||||
|
{
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* The singleton is statically allocated. */
|
||||||
|
_Py_FatalRefcountError("deallocating the token missing singleton");
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyTypeObject _PyContextTokenMissing_Type = {
|
PyTypeObject _PyContextTokenMissing_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"Token.MISSING",
|
"Token.MISSING",
|
||||||
sizeof(PyContextTokenMissing),
|
sizeof(_PyContextTokenMissing),
|
||||||
|
.tp_dealloc = (destructor)context_token_missing_tp_dealloc,
|
||||||
.tp_getattro = PyObject_GenericGetAttr,
|
.tp_getattro = PyObject_GenericGetAttr,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_repr = context_token_missing_tp_repr,
|
.tp_repr = context_token_missing_tp_repr,
|
||||||
|
@ -1263,17 +1267,7 @@ PyTypeObject _PyContextTokenMissing_Type = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_token_missing(void)
|
get_token_missing(void)
|
||||||
{
|
{
|
||||||
if (_token_missing != NULL) {
|
return Py_NewRef(&_Py_SINGLETON(context_token_missing));
|
||||||
return Py_NewRef(_token_missing);
|
|
||||||
}
|
|
||||||
|
|
||||||
_token_missing = (PyObject *)PyObject_New(
|
|
||||||
PyContextTokenMissing, &_PyContextTokenMissing_Type);
|
|
||||||
if (_token_missing == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Py_NewRef(_token_missing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1298,15 +1292,11 @@ _PyContext_ClearFreeList(PyInterpreterState *interp)
|
||||||
void
|
void
|
||||||
_PyContext_Fini(PyInterpreterState *interp)
|
_PyContext_Fini(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
if (_Py_IsMainInterpreter(interp)) {
|
|
||||||
Py_CLEAR(_token_missing);
|
|
||||||
}
|
|
||||||
_PyContext_ClearFreeList(interp);
|
_PyContext_ClearFreeList(interp);
|
||||||
#if defined(Py_DEBUG) && PyContext_MAXFREELIST > 0
|
#if defined(Py_DEBUG) && PyContext_MAXFREELIST > 0
|
||||||
struct _Py_context_state *state = &interp->context;
|
struct _Py_context_state *state = &interp->context;
|
||||||
state->numfree = -1;
|
state->numfree = -1;
|
||||||
#endif
|
#endif
|
||||||
_PyHamt_Fini(interp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -319,13 +319,6 @@ typedef struct {
|
||||||
} PyHamtNode_Array;
|
} PyHamtNode_Array;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_VAR_HEAD
|
|
||||||
uint32_t b_bitmap;
|
|
||||||
PyObject *b_array[1];
|
|
||||||
} PyHamtNode_Bitmap;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_VAR_HEAD
|
PyObject_VAR_HEAD
|
||||||
int32_t c_hash;
|
int32_t c_hash;
|
||||||
|
@ -333,10 +326,6 @@ typedef struct {
|
||||||
} PyHamtNode_Collision;
|
} PyHamtNode_Collision;
|
||||||
|
|
||||||
|
|
||||||
static PyHamtNode_Bitmap *_empty_bitmap_node;
|
|
||||||
static PyHamtObject *_empty_hamt;
|
|
||||||
|
|
||||||
|
|
||||||
static PyHamtObject *
|
static PyHamtObject *
|
||||||
hamt_alloc(void);
|
hamt_alloc(void);
|
||||||
|
|
||||||
|
@ -521,13 +510,16 @@ hamt_node_bitmap_new(Py_ssize_t size)
|
||||||
PyHamtNode_Bitmap *node;
|
PyHamtNode_Bitmap *node;
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
/* Since bitmap nodes are immutable, we can cache the instance
|
||||||
|
for size=0 and reuse it whenever we need an empty bitmap node.
|
||||||
|
*/
|
||||||
|
return (PyHamtNode *)Py_NewRef(&_Py_SINGLETON(hamt_bitmap_node_empty));
|
||||||
|
}
|
||||||
|
|
||||||
assert(size >= 0);
|
assert(size >= 0);
|
||||||
assert(size % 2 == 0);
|
assert(size % 2 == 0);
|
||||||
|
|
||||||
if (size == 0 && _empty_bitmap_node != NULL) {
|
|
||||||
return (PyHamtNode *)Py_NewRef(_empty_bitmap_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No freelist; allocate a new bitmap node */
|
/* No freelist; allocate a new bitmap node */
|
||||||
node = PyObject_GC_NewVar(
|
node = PyObject_GC_NewVar(
|
||||||
PyHamtNode_Bitmap, &_PyHamt_BitmapNode_Type, size);
|
PyHamtNode_Bitmap, &_PyHamt_BitmapNode_Type, size);
|
||||||
|
@ -545,13 +537,6 @@ hamt_node_bitmap_new(Py_ssize_t size)
|
||||||
|
|
||||||
_PyObject_GC_TRACK(node);
|
_PyObject_GC_TRACK(node);
|
||||||
|
|
||||||
if (size == 0 && _empty_bitmap_node == NULL) {
|
|
||||||
/* Since bitmap nodes are immutable, we can cache the instance
|
|
||||||
for size=0 and reuse it whenever we need an empty bitmap node.
|
|
||||||
*/
|
|
||||||
_empty_bitmap_node = (PyHamtNode_Bitmap*)Py_NewRef(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (PyHamtNode *)node;
|
return (PyHamtNode *)node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,6 +1127,16 @@ hamt_node_bitmap_dealloc(PyHamtNode_Bitmap *self)
|
||||||
Py_ssize_t len = Py_SIZE(self);
|
Py_ssize_t len = Py_SIZE(self);
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
if (Py_SIZE(self) == 0) {
|
||||||
|
/* The empty node is statically allocated. */
|
||||||
|
assert(self == &_Py_SINGLETON(hamt_bitmap_node_empty));
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
_Py_FatalRefcountError("deallocating the empty hamt node bitmap singleton");
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
Py_TRASHCAN_BEGIN(self, hamt_node_bitmap_dealloc)
|
Py_TRASHCAN_BEGIN(self, hamt_node_bitmap_dealloc)
|
||||||
|
|
||||||
|
@ -2431,33 +2426,15 @@ hamt_alloc(void)
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define _empty_hamt \
|
||||||
|
(&_Py_INTERP_SINGLETON(_PyInterpreterState_Get(), hamt_empty))
|
||||||
|
|
||||||
PyHamtObject *
|
PyHamtObject *
|
||||||
_PyHamt_New(void)
|
_PyHamt_New(void)
|
||||||
{
|
{
|
||||||
if (_empty_hamt != NULL) {
|
/* HAMT is an immutable object so we can easily cache an
|
||||||
/* HAMT is an immutable object so we can easily cache an
|
empty instance. */
|
||||||
empty instance. */
|
return (PyHamtObject*)Py_NewRef(_empty_hamt);
|
||||||
return (PyHamtObject*)Py_NewRef(_empty_hamt);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyHamtObject *o = hamt_alloc();
|
|
||||||
if (o == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
o->h_root = hamt_node_bitmap_new(0);
|
|
||||||
if (o->h_root == NULL) {
|
|
||||||
Py_DECREF(o);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
o->h_count = 0;
|
|
||||||
|
|
||||||
if (_empty_hamt == NULL) {
|
|
||||||
_empty_hamt = (PyHamtObject*)Py_NewRef(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
|
@ -2673,6 +2650,15 @@ hamt_tp_traverse(PyHamtObject *self, visitproc visit, void *arg)
|
||||||
static void
|
static void
|
||||||
hamt_tp_dealloc(PyHamtObject *self)
|
hamt_tp_dealloc(PyHamtObject *self)
|
||||||
{
|
{
|
||||||
|
if (self == _empty_hamt) {
|
||||||
|
/* The empty one is statically allocated. */
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
_Py_FatalRefcountError("deallocating the empty hamt singleton");
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
if (self->h_weakreflist != NULL) {
|
if (self->h_weakreflist != NULL) {
|
||||||
PyObject_ClearWeakRefs((PyObject*)self);
|
PyObject_ClearWeakRefs((PyObject*)self);
|
||||||
|
@ -2908,11 +2894,3 @@ PyTypeObject _PyHamt_CollisionNode_Type = {
|
||||||
.tp_free = PyObject_GC_Del,
|
.tp_free = PyObject_GC_Del,
|
||||||
.tp_hash = PyObject_HashNotImplemented,
|
.tp_hash = PyObject_HashNotImplemented,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_PyHamt_Fini(PyInterpreterState *interp)
|
|
||||||
{
|
|
||||||
Py_CLEAR(_empty_hamt);
|
|
||||||
Py_CLEAR(_empty_bitmap_node);
|
|
||||||
}
|
|
||||||
|
|
|
@ -127,6 +127,9 @@ NON_GENERATED_IMMORTAL_OBJECTS = [
|
||||||
# The generated ones come from generate_runtime_init().
|
# The generated ones come from generate_runtime_init().
|
||||||
'(PyObject *)&_Py_SINGLETON(bytes_empty)',
|
'(PyObject *)&_Py_SINGLETON(bytes_empty)',
|
||||||
'(PyObject *)&_Py_SINGLETON(tuple_empty)',
|
'(PyObject *)&_Py_SINGLETON(tuple_empty)',
|
||||||
|
'(PyObject *)&_Py_SINGLETON(hamt_bitmap_node_empty)',
|
||||||
|
'(PyObject *)&_Py_INTERP_SINGLETON(interp, hamt_empty)',
|
||||||
|
'(PyObject *)&_Py_SINGLETON(context_token_missing)',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -298,14 +298,6 @@ Objects/setobject.c - _dummy_struct -
|
||||||
Objects/setobject.c - _PySet_Dummy -
|
Objects/setobject.c - _PySet_Dummy -
|
||||||
Objects/sliceobject.c - _Py_EllipsisObject -
|
Objects/sliceobject.c - _Py_EllipsisObject -
|
||||||
|
|
||||||
#-----------------------
|
|
||||||
# other
|
|
||||||
|
|
||||||
# initialized once
|
|
||||||
Python/context.c - _token_missing -
|
|
||||||
Python/hamt.c - _empty_bitmap_node -
|
|
||||||
Python/hamt.c - _empty_hamt -
|
|
||||||
|
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
# global non-objects to fix in core code
|
# global non-objects to fix in core code
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Add table
Add a link
Reference in a new issue