https://github.com/python/cpython/commit/9357fdcaf0b08dac9396c17e8695b420fad887f8
commit: 9357fdcaf0b08dac9396c17e8695b420fad887f8
branch: main
author: Eric Snow <[email protected]>
committer: ericsnowcurrently <[email protected]>
date: 2024-11-07T09:32:42-07:00
summary:

gh-76785: Minor Cleanup of "Cross-interpreter" Code (gh-126457)

The primary objective here is to allow some later changes to be cleaner. Mostly 
this involves renaming things and moving a few things around.

* CrossInterpreterData -> XIData
* crossinterpdatafunc -> xidatafunc
* split out pycore_crossinterp_data_registry.h
* add _PyXIData_lookup_t

files:
A Include/internal/pycore_crossinterp_data_registry.h
M Include/internal/pycore_crossinterp.h
M Include/internal/pycore_runtime_init.h
M Makefile.pre.in
M Modules/_interpchannelsmodule.c
M Modules/_interpqueuesmodule.c
M Modules/_interpreters_common.h
M Modules/_interpretersmodule.c
M Modules/_testinternalcapi.c
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Python/crossinterp.c
M Python/crossinterp_data_lookup.h
M Python/pystate.c
M Tools/c-analyzer/cpython/_parser.py

diff --git a/Include/internal/pycore_crossinterp.h 
b/Include/internal/pycore_crossinterp.h
index 2dd165eae74850..e91e911feb38cc 100644
--- a/Include/internal/pycore_crossinterp.h
+++ b/Include/internal/pycore_crossinterp.h
@@ -38,28 +38,28 @@ extern int _Py_CallInInterpreterAndRawFree(
 /* cross-interpreter data */
 /**************************/
 
-typedef struct _xid _PyCrossInterpreterData;
-typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *);
+typedef struct _xid _PyXIData_t;
+typedef PyObject *(*xid_newobjectfunc)(_PyXIData_t *);
 typedef void (*xid_freefunc)(void *);
 
-// _PyCrossInterpreterData is similar to Py_buffer as an effectively
+// _PyXIData_t is similar to Py_buffer as an effectively
 // opaque struct that holds data outside the object machinery.  This
 // is necessary to pass safely between interpreters in the same process.
 struct _xid {
     // data is the cross-interpreter-safe derivation of a Python object
-    // (see _PyObject_GetCrossInterpreterData).  It will be NULL if the
+    // (see _PyObject_GetXIData).  It will be NULL if the
     // new_object func (below) encodes the data.
     void *data;
     // obj is the Python object from which the data was derived.  This
     // is non-NULL only if the data remains bound to the object in some
     // way, such that the object must be "released" (via a decref) when
     // the data is released.  In that case the code that sets the field,
-    // likely a registered "crossinterpdatafunc", is responsible for
+    // likely a registered "xidatafunc", is responsible for
     // ensuring it owns the reference (i.e. incref).
     PyObject *obj;
     // interp is the ID of the owning interpreter of the original
     // object.  It corresponds to the active interpreter when
-    // _PyObject_GetCrossInterpreterData() was called.  This should only
+    // _PyObject_GetXIData() was called.  This should only
     // be set by the cross-interpreter machinery.
     //
     // We use the ID rather than the PyInterpreterState to avoid issues
@@ -77,96 +77,77 @@ struct _xid {
     // okay (e.g. bytes) and for those types this field should be set
     // to NULL.  However, for most the data was allocated just for
     // cross-interpreter use, so it must be freed when
-    // _PyCrossInterpreterData_Release is called or the memory will
+    // _PyXIData_Release is called or the memory will
     // leak.  In that case, at the very least this field should be set
     // to PyMem_RawFree (the default if not explicitly set to NULL).
     // The call will happen with the original interpreter activated.
     xid_freefunc free;
 };
 
-PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void);
-PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data);
+PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void);
+PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);
 
-#define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data)
-#define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj)
-#define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid)
+#define _PyXIData_DATA(DATA) ((DATA)->data)
+#define _PyXIData_OBJ(DATA) ((DATA)->obj)
+#define _PyXIData_INTERPID(DATA) ((DATA)->interpid)
 // Users should not need getters for "new_object" or "free".
 
 
+/* getting cross-interpreter data */
+
+typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
+
+typedef struct _xid_lookup_state _PyXIData_lookup_t;
+
+PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *);
+PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *);
+PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *);
+
+
+/* using cross-interpreter data */
+
+PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);
+PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);
+PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);
+
+
 /* defining cross-interpreter data */
 
-PyAPI_FUNC(void) _PyCrossInterpreterData_Init(
-        _PyCrossInterpreterData *data,
+PyAPI_FUNC(void) _PyXIData_Init(
+        _PyXIData_t *data,
         PyInterpreterState *interp, void *shared, PyObject *obj,
         xid_newobjectfunc new_object);
-PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize(
-        _PyCrossInterpreterData *,
+PyAPI_FUNC(int) _PyXIData_InitWithSize(
+        _PyXIData_t *,
         PyInterpreterState *interp, const size_t, PyObject *,
         xid_newobjectfunc);
-PyAPI_FUNC(void) _PyCrossInterpreterData_Clear(
-        PyInterpreterState *, _PyCrossInterpreterData *);
+PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);
 
 // Normally the Init* functions are sufficient.  The only time
 // additional initialization might be needed is to set the "free" func,
 // though that should be infrequent.
-#define _PyCrossInterpreterData_SET_FREE(DATA, FUNC) \
+#define _PyXIData_SET_FREE(DATA, FUNC) \
     do { \
         (DATA)->free = (FUNC); \
     } while (0)
 // Additionally, some shareable types are essentially light wrappers
-// around other shareable types.  The crossinterpdatafunc of the wrapper
+// around other shareable types.  The xidatafunc of the wrapper
 // can often be implemented by calling the wrapped object's
-// crossinterpdatafunc and then changing the "new_object" function.
-// We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that,
+// xidatafunc and then changing the "new_object" function.
+// We have _PyXIData_SET_NEW_OBJECT() here for that,
 // but might be better to have a function like
-// _PyCrossInterpreterData_AdaptToWrapper() instead.
-#define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \
+// _PyXIData_AdaptToWrapper() instead.
+#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \
     do { \
         (DATA)->new_object = (FUNC); \
     } while (0)
 
 
-/* using cross-interpreter data */
-
-PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);
-PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, 
_PyCrossInterpreterData *);
-PyAPI_FUNC(PyObject *) 
_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *);
-PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);
-PyAPI_FUNC(int) 
_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *);
-
-
 /* cross-interpreter data registry */
 
-// For now we use a global registry of shareable classes.  An
-// alternative would be to add a tp_* slot for a class's
-// crossinterpdatafunc. It would be simpler and more efficient.
-
-typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *,
-                                   _PyCrossInterpreterData *);
-
-struct _xidregitem;
-
-struct _xidregitem {
-    struct _xidregitem *prev;
-    struct _xidregitem *next;
-    /* This can be a dangling pointer, but only if weakref is set. */
-    PyTypeObject *cls;
-    /* This is NULL for builtin types. */
-    PyObject *weakref;
-    size_t refcount;
-    crossinterpdatafunc getdata;
-};
-
-struct _xidregistry {
-    int global;  /* builtin types or heap types */
-    int initialized;
-    PyMutex mutex;
-    struct _xidregitem *head;
-};
-
-PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, 
crossinterpdatafunc);
-PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *);
-PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
+#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H
+#include "pycore_crossinterp_data_registry.h"
+#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H
 
 
 /*****************************/
@@ -175,14 +156,12 @@ PyAPI_FUNC(crossinterpdatafunc) 
_PyCrossInterpreterData_Lookup(PyObject *);
 
 struct _xi_runtime_state {
     // builtin types
-    // XXX Remove this field once we have a tp_* slot.
-    struct _xidregistry registry;
+    _PyXIData_lookup_t data_lookup;
 };
 
 struct _xi_state {
     // heap types
-    // XXX Remove this field once we have a tp_* slot.
-    struct _xidregistry registry;
+    _PyXIData_lookup_t data_lookup;
 
     // heap types
     PyObject *PyExc_NotShareableError;
@@ -190,7 +169,6 @@ struct _xi_state {
 
 extern PyStatus _PyXI_Init(PyInterpreterState *interp);
 extern void _PyXI_Fini(PyInterpreterState *interp);
-
 extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
 extern void _PyXI_FiniTypes(PyInterpreterState *interp);
 
diff --git a/Include/internal/pycore_crossinterp_data_registry.h 
b/Include/internal/pycore_crossinterp_data_registry.h
new file mode 100644
index 00000000000000..2990c6af62e952
--- /dev/null
+++ b/Include/internal/pycore_crossinterp_data_registry.h
@@ -0,0 +1,36 @@
+#ifndef Py_CORE_CROSSINTERP_DATA_REGISTRY_H
+#  error "this header must not be included directly"
+#endif
+
+
+// For now we use a global registry of shareable classes.  An
+// alternative would be to add a tp_* slot for a class's
+// xidatafunc. It would be simpler and more efficient.
+
+struct _xidregitem;
+
+struct _xidregitem {
+    struct _xidregitem *prev;
+    struct _xidregitem *next;
+    /* This can be a dangling pointer, but only if weakref is set. */
+    PyTypeObject *cls;
+    /* This is NULL for builtin types. */
+    PyObject *weakref;
+    size_t refcount;
+    xidatafunc getdata;
+};
+
+struct _xidregistry {
+    int global;  /* builtin types or heap types */
+    int initialized;
+    PyMutex mutex;
+    struct _xidregitem *head;
+};
+
+PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc);
+PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *);
+
+struct _xid_lookup_state {
+    // XXX Remove this field once we have a tp_* slot.
+    struct _xidregistry registry;
+};
diff --git a/Include/internal/pycore_runtime_init.h 
b/Include/internal/pycore_runtime_init.h
index e99febab2f3d57..bd3d704cb77730 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -50,8 +50,10 @@ extern PyTypeObject _PyExc_MemoryError;
             .next_id = -1, \
         }, \
         .xi = { \
-            .registry = { \
-                .global = 1, \
+            .data_lookup = { \
+                .registry = { \
+                    .global = 1, \
+                }, \
             }, \
         }, \
         /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
diff --git a/Makefile.pre.in b/Makefile.pre.in
index c650ecaf7be137..a337223d4d8608 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1203,6 +1203,7 @@ PYTHON_HEADERS= \
                $(srcdir)/Include/internal/pycore_context.h \
                $(srcdir)/Include/internal/pycore_critical_section.h \
                $(srcdir)/Include/internal/pycore_crossinterp.h \
+               $(srcdir)/Include/internal/pycore_crossinterp_data_registry.h \
                $(srcdir)/Include/internal/pycore_debug_offsets.h \
                $(srcdir)/Include/internal/pycore_descrobject.h \
                $(srcdir)/Include/internal/pycore_dict.h \
diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c
index 5dc032b46cac9a..b8d7dfb87cce0e 100644
--- a/Modules/_interpchannelsmodule.c
+++ b/Modules/_interpchannelsmodule.c
@@ -6,7 +6,7 @@
 #endif
 
 #include "Python.h"
-#include "pycore_crossinterp.h"   // struct _xid
+#include "pycore_crossinterp.h"   // _PyXIData_t
 #include "pycore_interp.h"        // _PyInterpreterState_LookUpID()
 #include "pycore_pystate.h"       // _PyInterpreterState_GetIDObject()
 
@@ -59,7 +59,7 @@ _globals (static struct globals):
                     first (struct _channelitem *):
                         next (struct _channelitem *):
                             ...
-                        data (_PyCrossInterpreterData *):
+                        data (_PyXIData_t *):
                             data (void *)
                             obj (PyObject *)
                             interpid (int64_t)
@@ -80,10 +80,10 @@ The above state includes the following allocations by the 
module:
    * 1 struct _channelqueue
 * for each item in each channel:
    * 1 struct _channelitem
-   * 1 _PyCrossInterpreterData
+   * 1 _PyXIData_t
 
 The only objects in that global state are the references held by each
-channel's queue, which are safely managed via the _PyCrossInterpreterData_*()
+channel's queue, which are safely managed via the _PyXIData_*()
 API..  The module does not create any objects that are shared globally.
 */
 
@@ -102,7 +102,7 @@ API..  The module does not create any objects that are 
shared globally.
 #define XID_FREE 2
 
 static int
-_release_xid_data(_PyCrossInterpreterData *data, int flags)
+_release_xid_data(_PyXIData_t *data, int flags)
 {
     int ignoreexc = flags & XID_IGNORE_EXC;
     PyObject *exc;
@@ -111,10 +111,10 @@ _release_xid_data(_PyCrossInterpreterData *data, int 
flags)
     }
     int res;
     if (flags & XID_FREE) {
-        res = _PyCrossInterpreterData_ReleaseAndRawFree(data);
+        res = _PyXIData_ReleaseAndRawFree(data);
     }
     else {
-        res = _PyCrossInterpreterData_Release(data);
+        res = _PyXIData_Release(data);
     }
     if (res < 0) {
         /* The owning interpreter is already destroyed. */
@@ -519,7 +519,7 @@ typedef struct _channelitem {
        This is necessary because item->data might be NULL,
        meaning the interpreter has been destroyed. */
     int64_t interpid;
-    _PyCrossInterpreterData *data;
+    _PyXIData_t *data;
     _waiting_t *waiting;
     int unboundop;
     struct _channelitem *next;
@@ -533,7 +533,7 @@ _channelitem_ID(_channelitem *item)
 
 static void
 _channelitem_init(_channelitem *item,
-                  int64_t interpid, _PyCrossInterpreterData *data,
+                  int64_t interpid, _PyXIData_t *data,
                   _waiting_t *waiting, int unboundop)
 {
     if (interpid < 0) {
@@ -541,8 +541,8 @@ _channelitem_init(_channelitem *item,
     }
     else {
         assert(data == NULL
-               || _PyCrossInterpreterData_INTERPID(data) < 0
-               || interpid == _PyCrossInterpreterData_INTERPID(data));
+               || _PyXIData_INTERPID(data) < 0
+               || interpid == _PyXIData_INTERPID(data));
     }
     *item = (_channelitem){
         .interpid = interpid,
@@ -580,7 +580,7 @@ _channelitem_clear(_channelitem *item)
 }
 
 static _channelitem *
-_channelitem_new(int64_t interpid, _PyCrossInterpreterData *data,
+_channelitem_new(int64_t interpid, _PyXIData_t *data,
                  _waiting_t *waiting, int unboundop)
 {
     _channelitem *item = GLOBAL_MALLOC(_channelitem);
@@ -611,7 +611,7 @@ _channelitem_free_all(_channelitem *item)
 
 static void
 _channelitem_popped(_channelitem *item,
-                    _PyCrossInterpreterData **p_data, _waiting_t **p_waiting,
+                    _PyXIData_t **p_data, _waiting_t **p_waiting,
                     int *p_unboundop)
 {
     assert(item->waiting == NULL || item->waiting->status == WAITING_ACQUIRED);
@@ -634,7 +634,7 @@ _channelitem_clear_interpreter(_channelitem *item)
         assert(item->unboundop != UNBOUND_REMOVE);
         return 0;
     }
-    assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid);
+    assert(_PyXIData_INTERPID(item->data) == item->interpid);
 
     switch (item->unboundop) {
     case UNBOUND_REMOVE:
@@ -691,7 +691,7 @@ _channelqueue_free(_channelqueue *queue)
 
 static int
 _channelqueue_put(_channelqueue *queue,
-                  int64_t interpid, _PyCrossInterpreterData *data,
+                  int64_t interpid, _PyXIData_t *data,
                   _waiting_t *waiting, int unboundop)
 {
     _channelitem *item = _channelitem_new(interpid, data, waiting, unboundop);
@@ -717,7 +717,7 @@ _channelqueue_put(_channelqueue *queue,
 
 static int
 _channelqueue_get(_channelqueue *queue,
-                  _PyCrossInterpreterData **p_data, _waiting_t **p_waiting,
+                  _PyXIData_t **p_data, _waiting_t **p_waiting,
                   int *p_unboundop)
 {
     _channelitem *item = queue->first;
@@ -769,7 +769,7 @@ _channelqueue_find(_channelqueue *queue, _channelitem_id_t 
itemid,
 
 static void
 _channelqueue_remove(_channelqueue *queue, _channelitem_id_t itemid,
-                     _PyCrossInterpreterData **p_data, _waiting_t **p_waiting)
+                     _PyXIData_t **p_data, _waiting_t **p_waiting)
 {
     _channelitem *prev = NULL;
     _channelitem *item = NULL;
@@ -1128,8 +1128,7 @@ _channel_free(_channel_state *chan)
 
 static int
 _channel_add(_channel_state *chan, int64_t interpid,
-             _PyCrossInterpreterData *data, _waiting_t *waiting,
-             int unboundop)
+             _PyXIData_t *data, _waiting_t *waiting, int unboundop)
 {
     int res = -1;
     PyThread_acquire_lock(chan->mutex, WAIT_LOCK);
@@ -1156,8 +1155,7 @@ _channel_add(_channel_state *chan, int64_t interpid,
 
 static int
 _channel_next(_channel_state *chan, int64_t interpid,
-              _PyCrossInterpreterData **p_data, _waiting_t **p_waiting,
-              int *p_unboundop)
+              _PyXIData_t **p_data, _waiting_t **p_waiting, int *p_unboundop)
 {
     int err = 0;
     PyThread_acquire_lock(chan->mutex, WAIT_LOCK);
@@ -1193,7 +1191,7 @@ _channel_next(_channel_state *chan, int64_t interpid,
 static void
 _channel_remove(_channel_state *chan, _channelitem_id_t itemid)
 {
-    _PyCrossInterpreterData *data = NULL;
+    _PyXIData_t *data = NULL;
     _waiting_t *waiting = NULL;
 
     PyThread_acquire_lock(chan->mutex, WAIT_LOCK);
@@ -1776,12 +1774,12 @@ channel_send(_channels *channels, int64_t cid, PyObject 
*obj,
     }
 
     // Convert the object to cross-interpreter data.
-    _PyCrossInterpreterData *data = GLOBAL_MALLOC(_PyCrossInterpreterData);
+    _PyXIData_t *data = GLOBAL_MALLOC(_PyXIData_t);
     if (data == NULL) {
         PyThread_release_lock(mutex);
         return -1;
     }
-    if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
+    if (_PyObject_GetXIData(obj, data) != 0) {
         PyThread_release_lock(mutex);
         GLOBAL_FREE(data);
         return -1;
@@ -1904,7 +1902,7 @@ channel_recv(_channels *channels, int64_t cid, PyObject 
**res, int *p_unboundop)
     // Past this point we are responsible for releasing the mutex.
 
     // Pop off the next item from the channel.
-    _PyCrossInterpreterData *data = NULL;
+    _PyXIData_t *data = NULL;
     _waiting_t *waiting = NULL;
     err = _channel_next(chan, interpid, &data, &waiting, p_unboundop);
     PyThread_release_lock(mutex);
@@ -1919,7 +1917,7 @@ channel_recv(_channels *channels, int64_t cid, PyObject 
**res, int *p_unboundop)
     }
 
     // Convert the data back to an object.
-    PyObject *obj = _PyCrossInterpreterData_NewObject(data);
+    PyObject *obj = _PyXIData_NewObject(data);
     if (obj == NULL) {
         assert(PyErr_Occurred());
         // It was allocated in channel_send(), so we free it.
@@ -2545,10 +2543,9 @@ struct _channelid_xid {
 };
 
 static PyObject *
-_channelid_from_xid(_PyCrossInterpreterData *data)
+_channelid_from_xid(_PyXIData_t *data)
 {
-    struct _channelid_xid *xid = \
-                (struct _channelid_xid *)_PyCrossInterpreterData_DATA(data);
+    struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data);
 
     // It might not be imported yet, so we can't use _get_current_module().
     PyObject *mod = PyImport_ImportModule(MODULE_NAME_STR);
@@ -2594,18 +2591,16 @@ _channelid_from_xid(_PyCrossInterpreterData *data)
 }
 
 static int
-_channelid_shared(PyThreadState *tstate, PyObject *obj,
-                  _PyCrossInterpreterData *data)
+_channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    if (_PyCrossInterpreterData_InitWithSize(
+    if (_PyXIData_InitWithSize(
             data, tstate->interp, sizeof(struct _channelid_xid), obj,
             _channelid_from_xid
             ) < 0)
     {
         return -1;
     }
-    struct _channelid_xid *xid = \
-                (struct _channelid_xid *)_PyCrossInterpreterData_DATA(data);
+    struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data);
     xid->cid = ((channelid *)obj)->cid;
     xid->end = ((channelid *)obj)->end;
     xid->resolve = ((channelid *)obj)->resolve;
@@ -2745,7 +2740,7 @@ _get_current_channelend_type(int end)
 }
 
 static PyObject *
-_channelend_from_xid(_PyCrossInterpreterData *data)
+_channelend_from_xid(_PyXIData_t *data)
 {
     channelid *cidobj = (channelid *)_channelid_from_xid(data);
     if (cidobj == NULL) {
@@ -2762,8 +2757,7 @@ _channelend_from_xid(_PyCrossInterpreterData *data)
 }
 
 static int
-_channelend_shared(PyThreadState *tstate, PyObject *obj,
-                    _PyCrossInterpreterData *data)
+_channelend_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
     PyObject *cidobj = PyObject_GetAttrString(obj, "_id");
     if (cidobj == NULL) {
@@ -2774,7 +2768,7 @@ _channelend_shared(PyThreadState *tstate, PyObject *obj,
     if (res < 0) {
         return -1;
     }
-    _PyCrossInterpreterData_SET_NEW_OBJECT(data, _channelend_from_xid);
+    _PyXIData_SET_NEW_OBJECT(data, _channelend_from_xid);
     return 0;
 }
 
diff --git a/Modules/_interpqueuesmodule.c b/Modules/_interpqueuesmodule.c
index 297a1763a98ce6..8d0e223db7ff19 100644
--- a/Modules/_interpqueuesmodule.c
+++ b/Modules/_interpqueuesmodule.c
@@ -6,7 +6,7 @@
 #endif
 
 #include "Python.h"
-#include "pycore_crossinterp.h"   // struct _xid
+#include "pycore_crossinterp.h"   // _PyXIData_t
 
 #define REGISTERS_HEAP_TYPES
 #define HAS_UNBOUND_ITEMS
@@ -30,7 +30,7 @@
 #define XID_FREE 2
 
 static int
-_release_xid_data(_PyCrossInterpreterData *data, int flags)
+_release_xid_data(_PyXIData_t *data, int flags)
 {
     int ignoreexc = flags & XID_IGNORE_EXC;
     PyObject *exc;
@@ -39,10 +39,10 @@ _release_xid_data(_PyCrossInterpreterData *data, int flags)
     }
     int res;
     if (flags & XID_FREE) {
-        res = _PyCrossInterpreterData_ReleaseAndRawFree(data);
+        res = _PyXIData_ReleaseAndRawFree(data);
     }
     else {
-        res = _PyCrossInterpreterData_Release(data);
+        res = _PyXIData_Release(data);
     }
     if (res < 0) {
         /* The owning interpreter is already destroyed. */
@@ -400,7 +400,7 @@ typedef struct _queueitem {
        This is necessary because item->data might be NULL,
        meaning the interpreter has been destroyed. */
     int64_t interpid;
-    _PyCrossInterpreterData *data;
+    _PyXIData_t *data;
     int fmt;
     int unboundop;
     struct _queueitem *next;
@@ -408,16 +408,15 @@ typedef struct _queueitem {
 
 static void
 _queueitem_init(_queueitem *item,
-                int64_t interpid, _PyCrossInterpreterData *data,
-                int fmt, int unboundop)
+                int64_t interpid, _PyXIData_t *data, int fmt, int unboundop)
 {
     if (interpid < 0) {
         interpid = _get_interpid(data);
     }
     else {
         assert(data == NULL
-               || _PyCrossInterpreterData_INTERPID(data) < 0
-               || interpid == _PyCrossInterpreterData_INTERPID(data));
+               || _PyXIData_INTERPID(data) < 0
+               || interpid == _PyXIData_INTERPID(data));
     }
     assert(check_unbound(unboundop));
     *item = (_queueitem){
@@ -447,8 +446,7 @@ _queueitem_clear(_queueitem *item)
 }
 
 static _queueitem *
-_queueitem_new(int64_t interpid, _PyCrossInterpreterData *data,
-               int fmt, int unboundop)
+_queueitem_new(int64_t interpid, _PyXIData_t *data, int fmt, int unboundop)
 {
     _queueitem *item = GLOBAL_MALLOC(_queueitem);
     if (item == NULL) {
@@ -478,7 +476,7 @@ _queueitem_free_all(_queueitem *item)
 
 static void
 _queueitem_popped(_queueitem *item,
-                  _PyCrossInterpreterData **p_data, int *p_fmt, int 
*p_unboundop)
+                  _PyXIData_t **p_data, int *p_fmt, int *p_unboundop)
 {
     *p_data = item->data;
     *p_fmt = item->fmt;
@@ -498,7 +496,7 @@ _queueitem_clear_interpreter(_queueitem *item)
         assert(item->unboundop != UNBOUND_REMOVE);
         return 0;
     }
-    assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid);
+    assert(_PyXIData_INTERPID(item->data) == item->interpid);
 
     switch (item->unboundop) {
     case UNBOUND_REMOVE:
@@ -633,7 +631,7 @@ _queue_unlock(_queue *queue)
 }
 
 static int
-_queue_add(_queue *queue, int64_t interpid, _PyCrossInterpreterData *data,
+_queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data,
            int fmt, int unboundop)
 {
     int err = _queue_lock(queue);
@@ -671,7 +669,7 @@ _queue_add(_queue *queue, int64_t interpid, 
_PyCrossInterpreterData *data,
 
 static int
 _queue_next(_queue *queue,
-            _PyCrossInterpreterData **p_data, int *p_fmt, int *p_unboundop)
+            _PyXIData_t **p_data, int *p_fmt, int *p_unboundop)
 {
     int err = _queue_lock(queue);
     if (err < 0) {
@@ -1138,17 +1136,17 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, 
int fmt, int unboundop)
     assert(queue != NULL);
 
     // Convert the object to cross-interpreter data.
-    _PyCrossInterpreterData *data = GLOBAL_MALLOC(_PyCrossInterpreterData);
+    _PyXIData_t *data = GLOBAL_MALLOC(_PyXIData_t);
     if (data == NULL) {
         _queue_unmark_waiter(queue, queues->mutex);
         return -1;
     }
-    if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
+    if (_PyObject_GetXIData(obj, data) != 0) {
         _queue_unmark_waiter(queue, queues->mutex);
         GLOBAL_FREE(data);
         return -1;
     }
-    assert(_PyCrossInterpreterData_INTERPID(data) == \
+    assert(_PyXIData_INTERPID(data) == \
            PyInterpreterState_GetID(PyInterpreterState_Get()));
 
     // Add the data to the queue.
@@ -1184,7 +1182,7 @@ queue_get(_queues *queues, int64_t qid,
     assert(queue != NULL);
 
     // Pop off the next item from the queue.
-    _PyCrossInterpreterData *data = NULL;
+    _PyXIData_t *data = NULL;
     err = _queue_next(queue, &data, p_fmt, p_unboundop);
     _queue_unmark_waiter(queue, queues->mutex);
     if (err != 0) {
@@ -1196,7 +1194,7 @@ queue_get(_queues *queues, int64_t qid,
     }
 
     // Convert the data back to an object.
-    PyObject *obj = _PyCrossInterpreterData_NewObject(data);
+    PyObject *obj = _PyXIData_NewObject(data);
     if (obj == NULL) {
         assert(PyErr_Occurred());
         // It was allocated in queue_put(), so we free it.
@@ -1258,8 +1256,7 @@ queue_get_count(_queues *queues, int64_t qid, Py_ssize_t 
*p_count)
 
 /* external Queue objects ***************************************************/
 
-static int _queueobj_shared(PyThreadState *,
-                            PyObject *, _PyCrossInterpreterData *);
+static int _queueobj_shared(PyThreadState *, PyObject *, _PyXIData_t *);
 
 static int
 set_external_queue_type(module_state *state, PyTypeObject *queue_type)
@@ -1339,9 +1336,9 @@ _queueid_xid_free(void *data)
 }
 
 static PyObject *
-_queueobj_from_xid(_PyCrossInterpreterData *data)
+_queueobj_from_xid(_PyXIData_t *data)
 {
-    int64_t qid = *(int64_t *)_PyCrossInterpreterData_DATA(data);
+    int64_t qid = *(int64_t *)_PyXIData_DATA(data);
     PyObject *qidobj = PyLong_FromLongLong(qid);
     if (qidobj == NULL) {
         return NULL;
@@ -1367,8 +1364,7 @@ _queueobj_from_xid(_PyCrossInterpreterData *data)
 }
 
 static int
-_queueobj_shared(PyThreadState *tstate, PyObject *queueobj,
-                 _PyCrossInterpreterData *data)
+_queueobj_shared(PyThreadState *tstate, PyObject *queueobj, _PyXIData_t *data)
 {
     PyObject *qidobj = PyObject_GetAttrString(queueobj, "_id");
     if (qidobj == NULL) {
@@ -1388,9 +1384,8 @@ _queueobj_shared(PyThreadState *tstate, PyObject 
*queueobj,
     if (raw == NULL) {
         return -1;
     }
-    _PyCrossInterpreterData_Init(data, tstate->interp, raw, NULL,
-                                 _queueobj_from_xid);
-    _PyCrossInterpreterData_SET_FREE(data, _queueid_xid_free);
+    _PyXIData_Init(data, tstate->interp, raw, NULL, _queueobj_from_xid);
+    _PyXIData_SET_FREE(data, _queueid_xid_free);
     return 0;
 }
 
diff --git a/Modules/_interpreters_common.h b/Modules/_interpreters_common.h
index 0d2e0c9efd3837..b0e31a33734dab 100644
--- a/Modules/_interpreters_common.h
+++ b/Modules/_interpreters_common.h
@@ -6,27 +6,27 @@
 
 
 static int
-ensure_xid_class(PyTypeObject *cls, crossinterpdatafunc getdata)
+ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
 {
     //assert(cls->tp_flags & Py_TPFLAGS_HEAPTYPE);
-    return _PyCrossInterpreterData_RegisterClass(cls, getdata);
+    return _PyXIData_RegisterClass(cls, getdata);
 }
 
 #ifdef REGISTERS_HEAP_TYPES
 static int
 clear_xid_class(PyTypeObject *cls)
 {
-    return _PyCrossInterpreterData_UnregisterClass(cls);
+    return _PyXIData_UnregisterClass(cls);
 }
 #endif
 
 
 static inline int64_t
-_get_interpid(_PyCrossInterpreterData *data)
+_get_interpid(_PyXIData_t *data)
 {
     int64_t interpid;
     if (data != NULL) {
-        interpid = _PyCrossInterpreterData_INTERPID(data);
+        interpid = _PyXIData_INTERPID(data);
         assert(!PyErr_Occurred());
     }
     else {
diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c
index 63f2bb38768511..95acdd69e53260 100644
--- a/Modules/_interpretersmodule.c
+++ b/Modules/_interpretersmodule.c
@@ -7,7 +7,7 @@
 
 #include "Python.h"
 #include "pycore_abstract.h"      // _PyIndex_Check()
-#include "pycore_crossinterp.h"   // struct _xid
+#include "pycore_crossinterp.h"   // _PyXIData_t
 #include "pycore_interp.h"        // _PyInterpreterState_IDIncref()
 #include "pycore_initconfig.h"    // _PyErr_SetFromPyStatus()
 #include "pycore_modsupport.h"    // _PyArg_BadArgument()
@@ -84,18 +84,18 @@ typedef struct {
 } XIBufferViewObject;
 
 static PyObject *
-xibufferview_from_xid(PyTypeObject *cls, _PyCrossInterpreterData *data)
+xibufferview_from_xid(PyTypeObject *cls, _PyXIData_t *data)
 {
-    assert(_PyCrossInterpreterData_DATA(data) != NULL);
-    assert(_PyCrossInterpreterData_OBJ(data) == NULL);
-    assert(_PyCrossInterpreterData_INTERPID(data) >= 0);
+    assert(_PyXIData_DATA(data) != NULL);
+    assert(_PyXIData_OBJ(data) == NULL);
+    assert(_PyXIData_INTERPID(data) >= 0);
     XIBufferViewObject *self = PyObject_Malloc(sizeof(XIBufferViewObject));
     if (self == NULL) {
         return NULL;
     }
     PyObject_Init((PyObject *)self, cls);
-    self->view = (Py_buffer *)_PyCrossInterpreterData_DATA(data);
-    self->interpid = _PyCrossInterpreterData_INTERPID(data);
+    self->view = (Py_buffer *)_PyXIData_DATA(data);
+    self->interpid = _PyXIData_INTERPID(data);
     return (PyObject *)self;
 }
 
@@ -154,7 +154,7 @@ static PyType_Spec XIBufferViewType_spec = {
 static PyTypeObject * _get_current_xibufferview_type(void);
 
 static PyObject *
-_memoryview_from_xid(_PyCrossInterpreterData *data)
+_memoryview_from_xid(_PyXIData_t *data)
 {
     PyTypeObject *cls = _get_current_xibufferview_type();
     if (cls == NULL) {
@@ -168,8 +168,7 @@ _memoryview_from_xid(_PyCrossInterpreterData *data)
 }
 
 static int
-_memoryview_shared(PyThreadState *tstate, PyObject *obj,
-                   _PyCrossInterpreterData *data)
+_memoryview_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
     Py_buffer *view = PyMem_RawMalloc(sizeof(Py_buffer));
     if (view == NULL) {
@@ -179,8 +178,7 @@ _memoryview_shared(PyThreadState *tstate, PyObject *obj,
         PyMem_RawFree(view);
         return -1;
     }
-    _PyCrossInterpreterData_Init(data, tstate->interp, view, NULL,
-                                 _memoryview_from_xid);
+    _PyXIData_Init(data, tstate->interp, view, NULL, _memoryview_from_xid);
     return 0;
 }
 
@@ -1183,7 +1181,7 @@ object_is_shareable(PyObject *self, PyObject *args, 
PyObject *kwds)
         return NULL;
     }
 
-    if (_PyObject_CheckCrossInterpreterData(obj) == 0) {
+    if (_PyObject_CheckXIData(obj) == 0) {
         Py_RETURN_TRUE;
     }
     PyErr_Clear();
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 883f32599fbc99..327a077671047c 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1787,11 +1787,10 @@ interpreter_refcount_linked(PyObject *self, PyObject 
*idobj)
 static void
 _xid_capsule_destructor(PyObject *capsule)
 {
-    _PyCrossInterpreterData *data = \
-            (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL);
+    _PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL);
     if (data != NULL) {
-        assert(_PyCrossInterpreterData_Release(data) == 0);
-        _PyCrossInterpreterData_Free(data);
+        assert(_PyXIData_Release(data) == 0);
+        _PyXIData_Free(data);
     }
 }
 
@@ -1803,18 +1802,18 @@ get_crossinterp_data(PyObject *self, PyObject *args)
         return NULL;
     }
 
-    _PyCrossInterpreterData *data = _PyCrossInterpreterData_New();
+    _PyXIData_t *data = _PyXIData_New();
     if (data == NULL) {
         return NULL;
     }
-    if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
-        _PyCrossInterpreterData_Free(data);
+    if (_PyObject_GetXIData(obj, data) != 0) {
+        _PyXIData_Free(data);
         return NULL;
     }
     PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor);
     if (capsule == NULL) {
-        assert(_PyCrossInterpreterData_Release(data) == 0);
-        _PyCrossInterpreterData_Free(data);
+        assert(_PyXIData_Release(data) == 0);
+        _PyXIData_Free(data);
     }
     return capsule;
 }
@@ -1827,12 +1826,11 @@ restore_crossinterp_data(PyObject *self, PyObject *args)
         return NULL;
     }
 
-    _PyCrossInterpreterData *data = \
-            (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL);
+    _PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL);
     if (data == NULL) {
         return NULL;
     }
-    return _PyCrossInterpreterData_NewObject(data);
+    return _PyXIData_NewObject(data);
 }
 
 
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index f840e7fd61f985..95552cade52b75 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -229,6 +229,7 @@
     <ClInclude Include="..\Include\internal\pycore_context.h" />
     <ClInclude Include="..\Include\internal\pycore_critical_section.h" />
     <ClInclude Include="..\Include\internal\pycore_crossinterp.h" />
+    <ClInclude 
Include="..\Include\internal\pycore_crossinterp_data_registry.h" />
     <ClInclude Include="..\Include\internal\pycore_debug_offsets.h" />
     <ClInclude Include="..\Include\internal\pycore_descrobject.h" />
     <ClInclude Include="..\Include\internal\pycore_dict.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters 
b/PCbuild/pythoncore.vcxproj.filters
index a930cd0b0b10c6..1708cf6e0b3a52 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -609,6 +609,9 @@
     <ClInclude Include="..\Include\internal\pycore_crossinterp.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude 
Include="..\Include\internal\pycore_crossinterp_data_registry.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_debug_offsets.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index 0aca322d987dba..2daba99988c12a 100644
--- a/Python/crossinterp.c
+++ b/Python/crossinterp.c
@@ -3,11 +3,14 @@
 
 #include "Python.h"
 #include "pycore_ceval.h"         // _Py_simple_func
-#include "pycore_crossinterp.h"   // struct _xid
+#include "pycore_crossinterp.h"   // _PyXIData_t
 #include "pycore_initconfig.h"    // _PyStatus_OK()
 #include "pycore_namespace.h"     //_PyNamespace_New()
 #include "pycore_pyerrors.h"      // _PyErr_Clear()
-#include "pycore_weakref.h"       // _PyWeakref_GET_REF()
+
+
+#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)
+#define _PyXI_GET_STATE(interp) (&(interp)->xi)
 
 
 /**************/
@@ -57,25 +60,24 @@ _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
 /* cross-interpreter data */
 /**************************/
 
-/* registry of {type -> crossinterpdatafunc} */
+/* registry of {type -> xidatafunc} */
 
 /* For now we use a global registry of shareable classes.  An
    alternative would be to add a tp_* slot for a class's
-   crossinterpdatafunc. It would be simpler and more efficient. */
+   xidatafunc. It would be simpler and more efficient. */
 
-static void xid_lookup_init(PyInterpreterState *);
-static void xid_lookup_fini(PyInterpreterState *);
-static crossinterpdatafunc lookup_getdata(PyInterpreterState *, PyObject *);
+static void xid_lookup_init(_PyXIData_lookup_t *);
+static void xid_lookup_fini(_PyXIData_lookup_t *);
+static xidatafunc lookup_getdata(PyInterpreterState *, PyObject *);
 #include "crossinterp_data_lookup.h"
 
 
 /* lifecycle */
 
-_PyCrossInterpreterData *
-_PyCrossInterpreterData_New(void)
+_PyXIData_t *
+_PyXIData_New(void)
 {
-    _PyCrossInterpreterData *xid = PyMem_RawMalloc(
-                                            sizeof(_PyCrossInterpreterData));
+    _PyXIData_t *xid = PyMem_RawMalloc(sizeof(_PyXIData_t));
     if (xid == NULL) {
         PyErr_NoMemory();
     }
@@ -83,10 +85,10 @@ _PyCrossInterpreterData_New(void)
 }
 
 void
-_PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid)
+_PyXIData_Free(_PyXIData_t *xid)
 {
     PyInterpreterState *interp = PyInterpreterState_Get();
-    _PyCrossInterpreterData_Clear(interp, xid);
+    _PyXIData_Clear(interp, xid);
     PyMem_RawFree(xid);
 }
 
@@ -94,20 +96,20 @@ _PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid)
 /* defining cross-interpreter data */
 
 static inline void
-_xidata_init(_PyCrossInterpreterData *data)
+_xidata_init(_PyXIData_t *data)
 {
     // If the value is being reused
     // then _xidata_clear() should have been called already.
     assert(data->data == NULL);
     assert(data->obj == NULL);
-    *data = (_PyCrossInterpreterData){0};
-    _PyCrossInterpreterData_INTERPID(data) = -1;
+    *data = (_PyXIData_t){0};
+    _PyXIData_INTERPID(data) = -1;
 }
 
 static inline void
-_xidata_clear(_PyCrossInterpreterData *data)
+_xidata_clear(_PyXIData_t *data)
 {
-    // _PyCrossInterpreterData only has two members that need to be
+    // _PyXIData_t only has two members that need to be
     // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
     // In both cases the original (owning) interpreter must be used,
     // which is the caller's responsibility to ensure.
@@ -121,10 +123,10 @@ _xidata_clear(_PyCrossInterpreterData *data)
 }
 
 void
-_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data,
-                             PyInterpreterState *interp,
-                             void *shared, PyObject *obj,
-                             xid_newobjectfunc new_object)
+_PyXIData_Init(_PyXIData_t *data,
+               PyInterpreterState *interp,
+               void *shared, PyObject *obj,
+               xid_newobjectfunc new_object)
 {
     assert(data != NULL);
     assert(new_object != NULL);
@@ -132,29 +134,29 @@ _PyCrossInterpreterData_Init(_PyCrossInterpreterData 
*data,
     data->data = shared;
     if (obj != NULL) {
         assert(interp != NULL);
-        // released in _PyCrossInterpreterData_Clear()
+        // released in _PyXIData_Clear()
         data->obj = Py_NewRef(obj);
     }
     // Ideally every object would know its owning interpreter.
     // Until then, we have to rely on the caller to identify it
     // (but we don't need it in all cases).
-    _PyCrossInterpreterData_INTERPID(data) = (interp != NULL)
+    _PyXIData_INTERPID(data) = (interp != NULL)
         ? PyInterpreterState_GetID(interp)
         : -1;
     data->new_object = new_object;
 }
 
 int
-_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,
-                                     PyInterpreterState *interp,
-                                     const size_t size, PyObject *obj,
-                                     xid_newobjectfunc new_object)
+_PyXIData_InitWithSize(_PyXIData_t *data,
+                       PyInterpreterState *interp,
+                       const size_t size, PyObject *obj,
+                       xid_newobjectfunc new_object)
 {
     assert(size > 0);
     // For now we always free the shared data in the same interpreter
     // where it was allocated, so the interpreter is required.
     assert(interp != NULL);
-    _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object);
+    _PyXIData_Init(data, interp, NULL, obj, new_object);
     data->data = PyMem_RawMalloc(size);
     if (data->data == NULL) {
         return -1;
@@ -164,14 +166,13 @@ 
_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,
 }
 
 void
-_PyCrossInterpreterData_Clear(PyInterpreterState *interp,
-                              _PyCrossInterpreterData *data)
+_PyXIData_Clear(PyInterpreterState *interp, _PyXIData_t *data)
 {
     assert(data != NULL);
     // This must be called in the owning interpreter.
     assert(interp == NULL
-           || _PyCrossInterpreterData_INTERPID(data) == -1
-           || _PyCrossInterpreterData_INTERPID(data) == 
PyInterpreterState_GetID(interp));
+           || _PyXIData_INTERPID(data) == -1
+           || _PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp));
     _xidata_clear(data);
 }
 
@@ -179,13 +180,13 @@ _PyCrossInterpreterData_Clear(PyInterpreterState *interp,
 /* using cross-interpreter data */
 
 static int
-_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data)
+_check_xidata(PyThreadState *tstate, _PyXIData_t *data)
 {
     // data->data can be anything, including NULL, so we don't check it.
 
     // data->obj may be NULL, so we don't check it.
 
-    if (_PyCrossInterpreterData_INTERPID(data) < 0) {
+    if (_PyXIData_INTERPID(data) < 0) {
         PyErr_SetString(PyExc_SystemError, "missing interp");
         return -1;
     }
@@ -221,10 +222,10 @@ _set_xid_lookup_failure(PyInterpreterState *interp,
 }
 
 int
-_PyObject_CheckCrossInterpreterData(PyObject *obj)
+_PyObject_CheckXIData(PyObject *obj)
 {
     PyInterpreterState *interp = PyInterpreterState_Get();
-    crossinterpdatafunc getdata = lookup_getdata(interp, obj);
+    xidatafunc getdata = lookup_getdata(interp, obj);
     if (getdata == NULL) {
         if (!PyErr_Occurred()) {
             _set_xid_lookup_failure(interp, obj, NULL);
@@ -235,18 +236,18 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj)
 }
 
 int
-_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
+_PyObject_GetXIData(PyObject *obj, _PyXIData_t *data)
 {
     PyThreadState *tstate = PyThreadState_Get();
     PyInterpreterState *interp = tstate->interp;
 
     // Reset data before re-populating.
-    *data = (_PyCrossInterpreterData){0};
-    _PyCrossInterpreterData_INTERPID(data) = -1;
+    *data = (_PyXIData_t){0};
+    _PyXIData_INTERPID(data) = -1;
 
     // Call the "getdata" func for the object.
     Py_INCREF(obj);
-    crossinterpdatafunc getdata = lookup_getdata(interp, obj);
+    xidatafunc getdata = lookup_getdata(interp, obj);
     if (getdata == NULL) {
         Py_DECREF(obj);
         if (!PyErr_Occurred()) {
@@ -261,9 +262,9 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, 
_PyCrossInterpreterData *data)
     }
 
     // Fill in the blanks and validate the result.
-    _PyCrossInterpreterData_INTERPID(data) = PyInterpreterState_GetID(interp);
+    _PyXIData_INTERPID(data) = PyInterpreterState_GetID(interp);
     if (_check_xidata(tstate, data) != 0) {
-        (void)_PyCrossInterpreterData_Release(data);
+        (void)_PyXIData_Release(data);
         return -1;
     }
 
@@ -271,7 +272,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, 
_PyCrossInterpreterData *data)
 }
 
 PyObject *
-_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
+_PyXIData_NewObject(_PyXIData_t *data)
 {
     return data->new_object(data);
 }
@@ -279,12 +280,12 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData 
*data)
 static int
 _call_clear_xidata(void *data)
 {
-    _xidata_clear((_PyCrossInterpreterData *)data);
+    _xidata_clear((_PyXIData_t *)data);
     return 0;
 }
 
 static int
-_xidata_release(_PyCrossInterpreterData *data, int rawfree)
+_xidata_release(_PyXIData_t *data, int rawfree)
 {
     if ((data->data == NULL || data->free == NULL) && data->obj == NULL) {
         // Nothing to release!
@@ -299,7 +300,7 @@ _xidata_release(_PyCrossInterpreterData *data, int rawfree)
 
     // Switch to the original interpreter.
     PyInterpreterState *interp = _PyInterpreterState_LookUpID(
-                                    _PyCrossInterpreterData_INTERPID(data));
+                                        _PyXIData_INTERPID(data));
     if (interp == NULL) {
         // The interpreter was already destroyed.
         // This function shouldn't have been called.
@@ -321,13 +322,13 @@ _xidata_release(_PyCrossInterpreterData *data, int 
rawfree)
 }
 
 int
-_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
+_PyXIData_Release(_PyXIData_t *data)
 {
     return _xidata_release(data, 0);
 }
 
 int
-_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data)
+_PyXIData_ReleaseAndRawFree(_PyXIData_t *data)
 {
     return _xidata_release(data, 1);
 }
@@ -446,15 +447,15 @@ _format_TracebackException(PyObject *tbexc)
 
 
 static int
-_release_xid_data(_PyCrossInterpreterData *data, int rawfree)
+_release_xid_data(_PyXIData_t *data, int rawfree)
 {
     PyObject *exc = PyErr_GetRaisedException();
     int res = rawfree
-        ? _PyCrossInterpreterData_Release(data)
-        : _PyCrossInterpreterData_ReleaseAndRawFree(data);
+        ? _PyXIData_Release(data)
+        : _PyXIData_ReleaseAndRawFree(data);
     if (res < 0) {
         /* The owning interpreter is already destroyed. */
-        _PyCrossInterpreterData_Clear(NULL, data);
+        _PyXIData_Clear(NULL, data);
         // XXX Emit a warning?
         PyErr_Clear();
     }
@@ -1094,8 +1095,8 @@ _PyXI_ApplyError(_PyXI_error *error)
 
 typedef struct _sharednsitem {
     const char *name;
-    _PyCrossInterpreterData *data;
-    // We could have a "PyCrossInterpreterData _data" field, so it would
+    _PyXIData_t *data;
+    // We could have a "PyXIData _data" field, so it would
     // be allocated as part of the item and avoid an extra allocation.
     // However, doing so adds a bunch of complexity because we must
     // ensure the item isn't freed before a pending call might happen
@@ -1131,7 +1132,7 @@ _sharednsitem_has_value(_PyXI_namespace_item *item, 
int64_t *p_interpid)
         return 0;
     }
     if (p_interpid != NULL) {
-        *p_interpid = _PyCrossInterpreterData_INTERPID(item->data);
+        *p_interpid = _PyXIData_INTERPID(item->data);
     }
     return 1;
 }
@@ -1141,12 +1142,12 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, 
PyObject *value)
 {
     assert(_sharednsitem_is_initialized(item));
     assert(item->data == NULL);
-    item->data = PyMem_RawMalloc(sizeof(_PyCrossInterpreterData));
+    item->data = PyMem_RawMalloc(sizeof(_PyXIData_t));
     if (item->data == NULL) {
         PyErr_NoMemory();
         return -1;
     }
-    if (_PyObject_GetCrossInterpreterData(value, item->data) != 0) {
+    if (_PyObject_GetXIData(value, item->data) != 0) {
         PyMem_RawFree(item->data);
         item->data = NULL;
         // The caller may want to propagate PyExc_NotShareableError
@@ -1159,7 +1160,7 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, 
PyObject *value)
 static void
 _sharednsitem_clear_value(_PyXI_namespace_item *item)
 {
-    _PyCrossInterpreterData *data = item->data;
+    _PyXIData_t *data = item->data;
     if (data != NULL) {
         item->data = NULL;
         int rawfree = 1;
@@ -1205,7 +1206,7 @@ _sharednsitem_apply(_PyXI_namespace_item *item, PyObject 
*ns, PyObject *dflt)
     }
     PyObject *value;
     if (item->data != NULL) {
-        value = _PyCrossInterpreterData_NewObject(item->data);
+        value = _PyXIData_NewObject(item->data);
         if (value == NULL) {
             Py_DECREF(name);
             return -1;
@@ -1776,7 +1777,10 @@ PyStatus
 _PyXI_Init(PyInterpreterState *interp)
 {
     // Initialize the XID lookup state (e.g. registry).
-    xid_lookup_init(interp);
+    if (_Py_IsMainInterpreter(interp)) {
+        xid_lookup_init(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup);
+    }
+    xid_lookup_init(&_PyXI_GET_STATE(interp)->data_lookup);
 
     // Initialize exceptions (heap types).
     if (_init_not_shareable_error_type(interp) < 0) {
@@ -1796,7 +1800,10 @@ _PyXI_Fini(PyInterpreterState *interp)
     _fini_not_shareable_error_type(interp);
 
     // Finalize the XID lookup state (e.g. registry).
-    xid_lookup_fini(interp);
+    xid_lookup_fini(&_PyXI_GET_STATE(interp)->data_lookup);
+    if (_Py_IsMainInterpreter(interp)) {
+        xid_lookup_fini(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup);
+    }
 }
 
 PyStatus
diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h
index 863919ad42fb97..88c662a3df00d6 100644
--- a/Python/crossinterp_data_lookup.h
+++ b/Python/crossinterp_data_lookup.h
@@ -1,8 +1,31 @@
+#include "pycore_weakref.h"       // _PyWeakref_GET_REF()
 
-static crossinterpdatafunc _lookup_getdata_from_registry(
-                                            PyInterpreterState *, PyObject *);
 
-static crossinterpdatafunc
+typedef struct _xidregistry dlregistry_t;
+typedef struct _xidregitem dlregitem_t;
+
+
+// forward
+static void _xidregistry_init(dlregistry_t *);
+static void _xidregistry_fini(dlregistry_t *);
+static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *, PyObject 
*);
+
+
+/* used in crossinterp.c */
+
+static void
+xid_lookup_init(_PyXIData_lookup_t *state)
+{
+    _xidregistry_init(&state->registry);
+}
+
+static void
+xid_lookup_fini(_PyXIData_lookup_t *state)
+{
+    _xidregistry_fini(&state->registry);
+}
+
+static xidatafunc
 lookup_getdata(PyInterpreterState *interp, PyObject *obj)
 {
    /* Cross-interpreter objects are looked up by exact match on the class.
@@ -11,8 +34,11 @@ lookup_getdata(PyInterpreterState *interp, PyObject *obj)
     return _lookup_getdata_from_registry(interp, obj);
 }
 
-crossinterpdatafunc
-_PyCrossInterpreterData_Lookup(PyObject *obj)
+
+/* exported API */
+
+xidatafunc
+_PyXIData_Lookup(PyObject *obj)
 {
     PyInterpreterState *interp = PyInterpreterState_Get();
     return lookup_getdata(interp, obj);
@@ -20,20 +46,20 @@ _PyCrossInterpreterData_Lookup(PyObject *obj)
 
 
 /***********************************************/
-/* a registry of {type -> crossinterpdatafunc} */
+/* a registry of {type -> xidatafunc} */
 /***********************************************/
 
 /* For now we use a global registry of shareable classes.  An
    alternative would be to add a tp_* slot for a class's
-   crossinterpdatafunc. It would be simpler and more efficient.  */
+   xidatafunc. It would be simpler and more efficient.  */
 
 
 /* registry lifecycle */
 
-static void _register_builtins_for_crossinterpreter_data(struct _xidregistry 
*);
+static void _register_builtins_for_crossinterpreter_data(dlregistry_t *);
 
 static void
-_xidregistry_init(struct _xidregistry *registry)
+_xidregistry_init(dlregistry_t *registry)
 {
     if (registry->initialized) {
         return;
@@ -47,10 +73,10 @@ _xidregistry_init(struct _xidregistry *registry)
     }
 }
 
-static void _xidregistry_clear(struct _xidregistry *);
+static void _xidregistry_clear(dlregistry_t *);
 
 static void
-_xidregistry_fini(struct _xidregistry *registry)
+_xidregistry_fini(dlregistry_t *registry)
 {
     if (!registry->initialized) {
         return;
@@ -60,32 +86,11 @@ _xidregistry_fini(struct _xidregistry *registry)
     _xidregistry_clear(registry);
 }
 
-static inline struct _xidregistry * _get_global_xidregistry(_PyRuntimeState *);
-static inline struct _xidregistry * _get_xidregistry(PyInterpreterState *);
-
-static void
-xid_lookup_init(PyInterpreterState *interp)
-{
-    if (_Py_IsMainInterpreter(interp)) {
-        _xidregistry_init(_get_global_xidregistry(interp->runtime));
-    }
-    _xidregistry_init(_get_xidregistry(interp));
-}
-
-static void
-xid_lookup_fini(PyInterpreterState *interp)
-{
-    _xidregistry_fini(_get_xidregistry(interp));
-    if (_Py_IsMainInterpreter(interp)) {
-        _xidregistry_fini(_get_global_xidregistry(interp->runtime));
-    }
-}
-
 
 /* registry thread safety */
 
 static void
-_xidregistry_lock(struct _xidregistry *registry)
+_xidregistry_lock(dlregistry_t *registry)
 {
     if (registry->global) {
         PyMutex_Lock(&registry->mutex);
@@ -94,7 +99,7 @@ _xidregistry_lock(struct _xidregistry *registry)
 }
 
 static void
-_xidregistry_unlock(struct _xidregistry *registry)
+_xidregistry_unlock(dlregistry_t *registry)
 {
     if (registry->global) {
         PyMutex_Unlock(&registry->mutex);
@@ -104,35 +109,34 @@ _xidregistry_unlock(struct _xidregistry *registry)
 
 /* accessing the registry */
 
-static inline struct _xidregistry *
+static inline dlregistry_t *
 _get_global_xidregistry(_PyRuntimeState *runtime)
 {
-    return &runtime->xi.registry;
+    return &runtime->xi.data_lookup.registry;
 }
 
-static inline struct _xidregistry *
+static inline dlregistry_t *
 _get_xidregistry(PyInterpreterState *interp)
 {
-    return &interp->xi.registry;
+    return &interp->xi.data_lookup.registry;
 }
 
-static inline struct _xidregistry *
+static inline dlregistry_t *
 _get_xidregistry_for_type(PyInterpreterState *interp, PyTypeObject *cls)
 {
-    struct _xidregistry *registry = _get_global_xidregistry(interp->runtime);
+    dlregistry_t *registry = _get_global_xidregistry(interp->runtime);
     if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
         registry = _get_xidregistry(interp);
     }
     return registry;
 }
 
-static struct _xidregitem * _xidregistry_remove_entry(
-        struct _xidregistry *, struct _xidregitem *);
+static dlregitem_t* _xidregistry_remove_entry(dlregistry_t *, dlregitem_t *);
 
-static struct _xidregitem *
-_xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls)
+static dlregitem_t *
+_xidregistry_find_type(dlregistry_t *xidregistry, PyTypeObject *cls)
 {
-    struct _xidregitem *cur = xidregistry->head;
+    dlregitem_t *cur = xidregistry->head;
     while (cur != NULL) {
         if (cur->weakref != NULL) {
             // cur is/was a heap type.
@@ -155,16 +159,16 @@ _xidregistry_find_type(struct _xidregistry *xidregistry, 
PyTypeObject *cls)
     return NULL;
 }
 
-static crossinterpdatafunc
+static xidatafunc
 _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj)
 {
     PyTypeObject *cls = Py_TYPE(obj);
 
-    struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls);
+    dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls);
     _xidregistry_lock(xidregistry);
 
-    struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls);
-    crossinterpdatafunc func = matched != NULL ? matched->getdata : NULL;
+    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
+    xidatafunc func = matched != NULL ? matched->getdata : NULL;
 
     _xidregistry_unlock(xidregistry);
     return func;
@@ -174,14 +178,14 @@ _lookup_getdata_from_registry(PyInterpreterState *interp, 
PyObject *obj)
 /* updating the registry */
 
 static int
-_xidregistry_add_type(struct _xidregistry *xidregistry,
-                      PyTypeObject *cls, crossinterpdatafunc getdata)
+_xidregistry_add_type(dlregistry_t *xidregistry,
+                      PyTypeObject *cls, xidatafunc getdata)
 {
-    struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem));
+    dlregitem_t *newhead = PyMem_RawMalloc(sizeof(dlregitem_t));
     if (newhead == NULL) {
         return -1;
     }
-    *newhead = (struct _xidregitem){
+    *newhead = (dlregitem_t){
         // We do not keep a reference, to avoid keeping the class alive.
         .cls = cls,
         .refcount = 1,
@@ -203,11 +207,10 @@ _xidregistry_add_type(struct _xidregistry *xidregistry,
     return 0;
 }
 
-static struct _xidregitem *
-_xidregistry_remove_entry(struct _xidregistry *xidregistry,
-                          struct _xidregitem *entry)
+static dlregitem_t *
+_xidregistry_remove_entry(dlregistry_t *xidregistry, dlregitem_t *entry)
 {
-    struct _xidregitem *next = entry->next;
+    dlregitem_t *next = entry->next;
     if (entry->prev != NULL) {
         assert(entry->prev->next == entry);
         entry->prev->next = next;
@@ -225,12 +228,12 @@ _xidregistry_remove_entry(struct _xidregistry 
*xidregistry,
 }
 
 static void
-_xidregistry_clear(struct _xidregistry *xidregistry)
+_xidregistry_clear(dlregistry_t *xidregistry)
 {
-    struct _xidregitem *cur = xidregistry->head;
+    dlregitem_t *cur = xidregistry->head;
     xidregistry->head = NULL;
     while (cur != NULL) {
-        struct _xidregitem *next = cur->next;
+        dlregitem_t *next = cur->next;
         Py_XDECREF(cur->weakref);
         PyMem_RawFree(cur);
         cur = next;
@@ -238,8 +241,7 @@ _xidregistry_clear(struct _xidregistry *xidregistry)
 }
 
 int
-_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
-                                      crossinterpdatafunc getdata)
+_PyXIData_RegisterClass(PyTypeObject *cls, xidatafunc getdata)
 {
     if (!PyType_Check(cls)) {
         PyErr_Format(PyExc_ValueError, "only classes may be registered");
@@ -252,10 +254,10 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
 
     int res = 0;
     PyInterpreterState *interp = _PyInterpreterState_GET();
-    struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls);
+    dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls);
     _xidregistry_lock(xidregistry);
 
-    struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls);
+    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
     if (matched != NULL) {
         assert(matched->getdata == getdata);
         matched->refcount += 1;
@@ -270,14 +272,14 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
 }
 
 int
-_PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls)
+_PyXIData_UnregisterClass(PyTypeObject *cls)
 {
     int res = 0;
     PyInterpreterState *interp = _PyInterpreterState_GET();
-    struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls);
+    dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls);
     _xidregistry_lock(xidregistry);
 
-    struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls);
+    dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
     if (matched != NULL) {
         assert(matched->refcount > 0);
         matched->refcount -= 1;
@@ -304,17 +306,16 @@ struct _shared_bytes_data {
 };
 
 static PyObject *
-_new_bytes_object(_PyCrossInterpreterData *data)
+_new_bytes_object(_PyXIData_t *data)
 {
     struct _shared_bytes_data *shared = (struct _shared_bytes_data 
*)(data->data);
     return PyBytes_FromStringAndSize(shared->bytes, shared->len);
 }
 
 static int
-_bytes_shared(PyThreadState *tstate, PyObject *obj,
-              _PyCrossInterpreterData *data)
+_bytes_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    if (_PyCrossInterpreterData_InitWithSize(
+    if (_PyXIData_InitWithSize(
             data, tstate->interp, sizeof(struct _shared_bytes_data), obj,
             _new_bytes_object
             ) < 0)
@@ -323,7 +324,7 @@ _bytes_shared(PyThreadState *tstate, PyObject *obj,
     }
     struct _shared_bytes_data *shared = (struct _shared_bytes_data 
*)data->data;
     if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) {
-        _PyCrossInterpreterData_Clear(tstate->interp, data);
+        _PyXIData_Clear(tstate->interp, data);
         return -1;
     }
     return 0;
@@ -338,17 +339,16 @@ struct _shared_str_data {
 };
 
 static PyObject *
-_new_str_object(_PyCrossInterpreterData *data)
+_new_str_object(_PyXIData_t *data)
 {
     struct _shared_str_data *shared = (struct _shared_str_data *)(data->data);
     return PyUnicode_FromKindAndData(shared->kind, shared->buffer, 
shared->len);
 }
 
 static int
-_str_shared(PyThreadState *tstate, PyObject *obj,
-            _PyCrossInterpreterData *data)
+_str_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    if (_PyCrossInterpreterData_InitWithSize(
+    if (_PyXIData_InitWithSize(
             data, tstate->interp, sizeof(struct _shared_str_data), obj,
             _new_str_object
             ) < 0)
@@ -365,14 +365,13 @@ _str_shared(PyThreadState *tstate, PyObject *obj,
 // int
 
 static PyObject *
-_new_long_object(_PyCrossInterpreterData *data)
+_new_long_object(_PyXIData_t *data)
 {
     return PyLong_FromSsize_t((Py_ssize_t)(data->data));
 }
 
 static int
-_long_shared(PyThreadState *tstate, PyObject *obj,
-             _PyCrossInterpreterData *data)
+_long_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
     /* Note that this means the size of shareable ints is bounded by
      * sys.maxsize.  Hence on 32-bit architectures that is half the
@@ -385,8 +384,7 @@ _long_shared(PyThreadState *tstate, PyObject *obj,
         }
         return -1;
     }
-    _PyCrossInterpreterData_Init(data, tstate->interp, (void *)value, NULL,
-            _new_long_object);
+    _PyXIData_Init(data, tstate->interp, (void *)value, NULL, 
_new_long_object);
     // data->obj and data->free remain NULL
     return 0;
 }
@@ -394,17 +392,16 @@ _long_shared(PyThreadState *tstate, PyObject *obj,
 // float
 
 static PyObject *
-_new_float_object(_PyCrossInterpreterData *data)
+_new_float_object(_PyXIData_t *data)
 {
     double * value_ptr = data->data;
     return PyFloat_FromDouble(*value_ptr);
 }
 
 static int
-_float_shared(PyThreadState *tstate, PyObject *obj,
-             _PyCrossInterpreterData *data)
+_float_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    if (_PyCrossInterpreterData_InitWithSize(
+    if (_PyXIData_InitWithSize(
             data, tstate->interp, sizeof(double), NULL,
             _new_float_object
             ) < 0)
@@ -419,18 +416,16 @@ _float_shared(PyThreadState *tstate, PyObject *obj,
 // None
 
 static PyObject *
-_new_none_object(_PyCrossInterpreterData *data)
+_new_none_object(_PyXIData_t *data)
 {
     // XXX Singleton refcounts are problematic across interpreters...
     return Py_NewRef(Py_None);
 }
 
 static int
-_none_shared(PyThreadState *tstate, PyObject *obj,
-             _PyCrossInterpreterData *data)
+_none_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL,
-            _new_none_object);
+    _PyXIData_Init(data, tstate->interp, NULL, NULL, _new_none_object);
     // data->data, data->obj and data->free remain NULL
     return 0;
 }
@@ -438,7 +433,7 @@ _none_shared(PyThreadState *tstate, PyObject *obj,
 // bool
 
 static PyObject *
-_new_bool_object(_PyCrossInterpreterData *data)
+_new_bool_object(_PyXIData_t *data)
 {
     if (data->data){
         Py_RETURN_TRUE;
@@ -447,10 +442,9 @@ _new_bool_object(_PyCrossInterpreterData *data)
 }
 
 static int
-_bool_shared(PyThreadState *tstate, PyObject *obj,
-             _PyCrossInterpreterData *data)
+_bool_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
-    _PyCrossInterpreterData_Init(data, tstate->interp,
+    _PyXIData_Init(data, tstate->interp,
             (void *) (Py_IsTrue(obj) ? (uintptr_t) 1 : (uintptr_t) 0), NULL,
             _new_bool_object);
     // data->obj and data->free remain NULL
@@ -461,11 +455,11 @@ _bool_shared(PyThreadState *tstate, PyObject *obj,
 
 struct _shared_tuple_data {
     Py_ssize_t len;
-    _PyCrossInterpreterData **data;
+    _PyXIData_t **data;
 };
 
 static PyObject *
-_new_tuple_object(_PyCrossInterpreterData *data)
+_new_tuple_object(_PyXIData_t *data)
 {
     struct _shared_tuple_data *shared = (struct _shared_tuple_data 
*)(data->data);
     PyObject *tuple = PyTuple_New(shared->len);
@@ -474,7 +468,7 @@ _new_tuple_object(_PyCrossInterpreterData *data)
     }
 
     for (Py_ssize_t i = 0; i < shared->len; i++) {
-        PyObject *item = _PyCrossInterpreterData_NewObject(shared->data[i]);
+        PyObject *item = _PyXIData_NewObject(shared->data[i]);
         if (item == NULL){
             Py_DECREF(tuple);
             return NULL;
@@ -493,8 +487,8 @@ _tuple_shared_free(void* data)
 #endif
     for (Py_ssize_t i = 0; i < shared->len; i++) {
         if (shared->data[i] != NULL) {
-            assert(_PyCrossInterpreterData_INTERPID(shared->data[i]) == 
interpid);
-            _PyCrossInterpreterData_Release(shared->data[i]);
+            assert(_PyXIData_INTERPID(shared->data[i]) == interpid);
+            _PyXIData_Release(shared->data[i]);
             PyMem_RawFree(shared->data[i]);
             shared->data[i] = NULL;
         }
@@ -504,8 +498,7 @@ _tuple_shared_free(void* data)
 }
 
 static int
-_tuple_shared(PyThreadState *tstate, PyObject *obj,
-             _PyCrossInterpreterData *data)
+_tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
 {
     Py_ssize_t len = PyTuple_GET_SIZE(obj);
     if (len < 0) {
@@ -518,14 +511,14 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj,
     }
 
     shared->len = len;
-    shared->data = (_PyCrossInterpreterData **) PyMem_Calloc(shared->len, 
sizeof(_PyCrossInterpreterData *));
+    shared->data = (_PyXIData_t **) PyMem_Calloc(shared->len, 
sizeof(_PyXIData_t *));
     if (shared->data == NULL) {
         PyErr_NoMemory();
         return -1;
     }
 
     for (Py_ssize_t i = 0; i < shared->len; i++) {
-        _PyCrossInterpreterData *data = _PyCrossInterpreterData_New();
+        _PyXIData_t *data = _PyXIData_New();
         if (data == NULL) {
             goto error;  // PyErr_NoMemory already set
         }
@@ -533,7 +526,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj,
 
         int res = -1;
         if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) {
-            res = _PyObject_GetCrossInterpreterData(item, data);
+            res = _PyObject_GetXIData(item, data);
             _Py_LeaveRecursiveCallTstate(tstate);
         }
         if (res < 0) {
@@ -542,8 +535,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj,
         }
         shared->data[i] = data;
     }
-    _PyCrossInterpreterData_Init(
-            data, tstate->interp, shared, obj, _new_tuple_object);
+    _PyXIData_Init(data, tstate->interp, shared, obj, _new_tuple_object);
     data->free = _tuple_shared_free;
     return 0;
 
@@ -555,7 +547,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj,
 // registration
 
 static void
-_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
+_register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
 {
     // None
     if (_xidregistry_add_type(xidregistry, (PyTypeObject 
*)PyObject_Type(Py_None), _none_shared) != 0) {
diff --git a/Python/pystate.c b/Python/pystate.c
index ded5fde9c4bb51..24ee73c145cbcc 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -396,7 +396,7 @@ _Py_COMP_DIAG_POP
 #define LOCKS_INIT(runtime) \
     { \
         &(runtime)->interpreters.mutex, \
-        &(runtime)->xi.registry.mutex, \
+        &(runtime)->xi.data_lookup.registry.mutex, \
         &(runtime)->unicode_state.ids.mutex, \
         &(runtime)->imports.extensions.mutex, \
         &(runtime)->ceval.pending_mainthread.mutex, \
diff --git a/Tools/c-analyzer/cpython/_parser.py 
b/Tools/c-analyzer/cpython/_parser.py
index 3a73f65f8ff7b3..21be53e78841d5 100644
--- a/Tools/c-analyzer/cpython/_parser.py
+++ b/Tools/c-analyzer/cpython/_parser.py
@@ -290,6 +290,7 @@ def clean_lines(text):
 Modules/_sre/sre_lib.h LOCAL(type)     static inline type
 Modules/_sre/sre_lib.h SRE(F)  sre_ucs2_##F
 Objects/stringlib/codecs.h     STRINGLIB_IS_UNICODE    1
+Include/internal/pycore_crossinterp_data_registry.h    
Py_CORE_CROSSINTERP_DATA_REGISTRY_H     1
 
 # @end=tsv@
 ''')[1:]

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to