gh-132775: Add _PyFunction_GetXIData() (gh-133481)

This commit is contained in:
Eric Snow 2025-05-12 16:10:56 -06:00 committed by GitHub
parent 121ed71f4e
commit 8cf4947b0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 103 additions and 0 deletions

View file

@ -10,6 +10,7 @@
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_namespace.h" // _PyNamespace_New()
#include "pycore_pythonrun.h" // _Py_SourceAsString()
#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_typeobject.h" // _PyStaticType_InitBuiltin()

View file

@ -677,6 +677,60 @@ _PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
return 0;
}
// function
PyObject *
_PyFunction_FromXIData(_PyXIData_t *xidata)
{
// For now "stateless" functions are the only ones we must accommodate.
PyObject *code = _PyMarshal_ReadObjectFromXIData(xidata);
if (code == NULL) {
return NULL;
}
// Create a new function.
assert(PyCode_Check(code));
PyObject *globals = PyDict_New();
if (globals == NULL) {
Py_DECREF(code);
return NULL;
}
PyObject *func = PyFunction_New(code, globals);
Py_DECREF(code);
Py_DECREF(globals);
return func;
}
int
_PyFunction_GetXIData(PyThreadState *tstate, PyObject *func,
_PyXIData_t *xidata)
{
if (!PyFunction_Check(func)) {
const char *msg = "expected a function, got %R";
format_notshareableerror(tstate, NULL, 0, msg, func);
return -1;
}
if (_PyFunction_VerifyStateless(tstate, func) < 0) {
PyObject *cause = _PyErr_GetRaisedException(tstate);
assert(cause != NULL);
const char *msg = "only stateless functions are shareable";
set_notshareableerror(tstate, cause, 0, msg);
Py_DECREF(cause);
return -1;
}
PyObject *code = PyFunction_GET_CODE(func);
// Ideally code objects would be immortal and directly shareable.
// In the meantime, we use marshal.
if (_PyMarshal_GetXIData(tstate, code, xidata) < 0) {
return -1;
}
// Replace _PyMarshal_ReadObjectFromXIData.
// (_PyFunction_FromXIData() will call it.)
_PyXIData_SET_NEW_OBJECT(xidata, _PyFunction_FromXIData);
return 0;
}
// registration
@ -717,4 +771,6 @@ _register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
if (_xidregistry_add_type(xidregistry, &PyTuple_Type, _tuple_shared) != 0) {
Py_FatalError("could not register tuple for cross-interpreter sharing");
}
// For now, we do not register PyCode_Type or PyFunction_Type.
}