@@ -677,6 +677,60 @@ _PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
677
677
return 0 ;
678
678
}
679
679
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
+
680
734
681
735
// registration
682
736
@@ -717,4 +771,6 @@ _register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
717
771
if (_xidregistry_add_type (xidregistry , & PyTuple_Type , _tuple_shared ) != 0 ) {
718
772
Py_FatalError ("could not register tuple for cross-interpreter sharing" );
719
773
}
774
+
775
+ // For now, we do not register PyCode_Type or PyFunction_Type.
720
776
}
0 commit comments