gh-76785: Improved Subinterpreters Compatibility with 3.12 (gh-115424)

For the most part, these changes make is substantially easier to backport subinterpreter-related code to 3.12, especially the related modules (e.g. _xxsubinterpreters). The main motivation is to support releasing a PyPI package with the 3.13 capabilities compiled for 3.12.

A lot of the changes here involve either hiding details behind macros/functions or splitting up some files.
This commit is contained in:
Eric Snow 2024-02-13 14:56:49 -07:00 committed by GitHub
parent 206f73dc5f
commit 514b1c91b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 857 additions and 719 deletions

View file

@ -8,6 +8,15 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
// We hide some of the newer PyCodeObject fields behind macros.
// This helps with backporting certain changes to 3.12.
#define _PyCode_HAS_EXECUTORS(CODE) \
(CODE->co_executors != NULL)
#define _PyCode_HAS_INSTRUMENTATION(CODE) \
(CODE->_co_instrumentation_version > 0)
#define CODE_MAX_WATCHERS 8
/* PEP 659

View file

@ -87,6 +87,11 @@ struct _xid {
PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void);
PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data);
#define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data)
#define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj)
#define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid)
// Users should not need getters for "new_object" or "free".
/* defining cross-interpreter data */
@ -101,6 +106,25 @@ PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize(
PyAPI_FUNC(void) _PyCrossInterpreterData_Clear(
PyInterpreterState *, _PyCrossInterpreterData *);
// 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) \
do { \
(DATA)->free = (FUNC); \
} while (0)
// Additionally, some shareable types are essentially light wrappers
// around other shareable types. The crossinterpdatafunc 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,
// but might be better to have a function like
// _PyCrossInterpreterData_AdaptToWrapper() instead.
#define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \
do { \
(DATA)->new_object = (FUNC); \
} while (0)
/* using cross-interpreter data */
@ -170,6 +194,8 @@ extern void _PyXI_Fini(PyInterpreterState *interp);
extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
extern void _PyXI_FiniTypes(PyInterpreterState *interp);
#define _PyInterpreterState_GetXIState(interp) (&(interp)->xi)
/***************************/
/* short-term data sharing */

View file

@ -13,6 +13,13 @@ extern "C" {
#include "pycore_brc.h" // struct _brc_thread_state
static inline void
_PyThreadState_SetWhence(PyThreadState *tstate, int whence)
{
tstate->_whence = whence;
}
// Every PyThreadState is actually allocated as a _PyThreadStateImpl. The
// PyThreadState fields are exposed as part of the C API, although most fields
// are intended to be private. The _PyThreadStateImpl fields not exposed.