@@ -677,6 +677,60 @@ _PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
677677 return 0 ;
678678}
679679
680+ // function
681+
682+ PyObject *
683+ _PyFunction_FromXIData (_PyXIData_t * xidata )
684+ {
685+ // For now "stateless" functions are the only ones we must accommodate.
686+
687+ PyObject * code = _PyMarshal_ReadObjectFromXIData (xidata );
688+ if (code == NULL ) {
689+ return NULL ;
690+ }
691+ // Create a new function.
692+ assert (PyCode_Check (code ));
693+ PyObject * globals = PyDict_New ();
694+ if (globals == NULL ) {
695+ Py_DECREF (code );
696+ return NULL ;
697+ }
698+ PyObject * func = PyFunction_New (code , globals );
699+ Py_DECREF (code );
700+ Py_DECREF (globals );
701+ return func ;
702+ }
703+
704+ int
705+ _PyFunction_GetXIData (PyThreadState * tstate , PyObject * func ,
706+ _PyXIData_t * xidata )
707+ {
708+ if (!PyFunction_Check (func )) {
709+ const char * msg = "expected a function, got %R" ;
710+ format_notshareableerror (tstate , NULL , 0 , msg , func );
711+ return -1 ;
712+ }
713+ if (_PyFunction_VerifyStateless (tstate , func ) < 0 ) {
714+ PyObject * cause = _PyErr_GetRaisedException (tstate );
715+ assert (cause != NULL );
716+ const char * msg = "only stateless functions are shareable" ;
717+ set_notshareableerror (tstate , cause , 0 , msg );
718+ Py_DECREF (cause );
719+ return -1 ;
720+ }
721+ PyObject * code = PyFunction_GET_CODE (func );
722+
723+ // Ideally code objects would be immortal and directly shareable.
724+ // In the meantime, we use marshal.
725+ if (_PyMarshal_GetXIData (tstate , code , xidata ) < 0 ) {
726+ return -1 ;
727+ }
728+ // Replace _PyMarshal_ReadObjectFromXIData.
729+ // (_PyFunction_FromXIData() will call it.)
730+ _PyXIData_SET_NEW_OBJECT (xidata , _PyFunction_FromXIData );
731+ return 0 ;
732+ }
733+
680734
681735// registration
682736
@@ -717,4 +771,6 @@ _register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
717771 if (_xidregistry_add_type (xidregistry , & PyTuple_Type , _tuple_shared ) != 0 ) {
718772 Py_FatalError ("could not register tuple for cross-interpreter sharing" );
719773 }
774+
775+ // For now, we do not register PyCode_Type or PyFunction_Type.
720776}
0 commit comments