@@ -127,27 +127,52 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
127
127
assert (_PyErr_Occurred (tstate ));
128
128
return -1 ;
129
129
}
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 ;
135
141
}
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 ;
144
147
}
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
+ }
149
173
}
150
174
175
+ Py_DECREF (key );
151
176
main -> cached = (struct sync_module_result ){
152
177
.module = mod ,
153
178
.loaded = loaded ,
@@ -158,6 +183,7 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
158
183
sync_module_capture_exc (tstate , main );
159
184
Py_XDECREF (loaded );
160
185
Py_DECREF (mod );
186
+ Py_XDECREF (key );
161
187
return -1 ;
162
188
}
163
189
0 commit comments