diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2025-05-12 22:37:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-12 22:37:55 (GMT) |
commit | 3467656b18d188511df33d05be918f6d1f6ceae5 (patch) | |
tree | bc41ff2308a7d8bc17a6799bf16da2bb0ca57115 /Python/crossinterp_data_lookup.h | |
parent | c1aa5f82d9442f5a15676e962aba3501951c542e (diff) | |
download | cpython-3467656b18d188511df33d05be918f6d1f6ceae5.zip cpython-3467656b18d188511df33d05be918f6d1f6ceae5.tar.gz cpython-3467656b18d188511df33d05be918f6d1f6ceae5.tar.bz2 |
[3.14] gh-132775: Add _PyFunction_GetXIData() (gh-133955)
(cherry picked from commit 8cf4947b0f, AKA gh-133481)
Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
Diffstat (limited to 'Python/crossinterp_data_lookup.h')
-rw-r--r-- | Python/crossinterp_data_lookup.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index 231537c..d69927d 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -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. } |