@@ -127,27 +127,52 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
127127 assert (_PyErr_Occurred (tstate ));
128128 return -1 ;
129129 }
130-
131- // It wasn't already loaded from file.
132- PyObject * loaded = PyModule_NewObject (& _Py_ID (__main__ ));
133- if (loaded == NULL ) {
134- goto error ;
130+ PyObject * loaded = NULL ;
131+
132+ // Try the per-interpreter cache for the loaded module.
133+ // XXX Store it in sys.modules?
134+ PyObject * interpns = PyInterpreterState_GetDict (tstate -> interp );
135+ assert (interpns != NULL );
136+ PyObject * key = PyUnicode_FromString ("CACHED_MODULE_NS___main__" );
137+ if (key == NULL ) {
138+ // It's probably unrecoverable, so don't bother caching the error.
139+ Py_DECREF (mod );
140+ return -1 ;
135141 }
136- PyObject * ns = _PyModule_GetDict (loaded );
137-
138- // We don't want to trigger "if __name__ == '__main__':",
139- // so we use a bogus module name.
140- PyObject * loaded_ns =
141- runpy_run_path (main -> filename , "<fake __main__>" );
142- if (loaded_ns == NULL ) {
143- goto error ;
142+ else if (PyDict_GetItemRef (interpns , key , & loaded ) < 0 ) {
143+ // It's probably unrecoverable, so don't bother caching the error.
144+ Py_DECREF (mod );
145+ Py_DECREF (key );
146+ return -1 ;
144147 }
145- int res = PyDict_Update (ns , loaded_ns );
146- Py_DECREF (loaded_ns );
147- if (res < 0 ) {
148- goto error ;
148+ else if (loaded == NULL ) {
149+ // It wasn't already loaded from file.
150+ loaded = PyModule_NewObject (& _Py_ID (__main__ ));
151+ if (loaded == NULL ) {
152+ goto error ;
153+ }
154+ PyObject * ns = _PyModule_GetDict (loaded );
155+
156+ // We don't want to trigger "if __name__ == '__main__':",
157+ // so we use a bogus module name.
158+ PyObject * loaded_ns =
159+ runpy_run_path (main -> filename , "<fake __main__>" );
160+ if (loaded_ns == NULL ) {
161+ goto error ;
162+ }
163+ int res = PyDict_Update (ns , loaded_ns );
164+ Py_DECREF (loaded_ns );
165+ if (res < 0 ) {
166+ goto error ;
167+ }
168+
169+ // Set the per-interpreter cache entry.
170+ if (PyDict_SetItem (interpns , key , loaded ) < 0 ) {
171+ goto error ;
172+ }
149173 }
150174
175+ Py_DECREF (key );
151176 main -> cached = (struct sync_module_result ){
152177 .module = mod ,
153178 .loaded = loaded ,
@@ -158,6 +183,7 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
158183 sync_module_capture_exc (tstate , main );
159184 Py_XDECREF (loaded );
160185 Py_DECREF (mod );
186+ Py_XDECREF (key );
161187 return -1 ;
162188}
163189
0 commit comments