@@ -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