@@ -32,6 +32,7 @@ JL_DLLEXPORT int jl_lineno = 0; // need to update jl_critical_error if this is T
3232JL_DLLEXPORT const char * jl_filename = "none" ; // need to update jl_critical_error if this is TLS
3333
3434htable_t jl_current_modules ;
35+ jl_mutex_t jl_modules_mutex ;
3536
3637JL_DLLEXPORT void jl_add_standard_imports (jl_module_t * m )
3738{
@@ -135,7 +136,9 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
135136 jl_module_t * newm = jl_new_module (name );
136137 jl_value_t * form = (jl_value_t * )newm ;
137138 JL_GC_PUSH1 (& form );
139+ JL_LOCK (& jl_modules_mutex );
138140 ptrhash_put (& jl_current_modules , (void * )newm , (void * )((uintptr_t )HT_NOTFOUND + 1 ));
141+ JL_UNLOCK (& jl_modules_mutex );
139142
140143 // copy parent environment info into submodule
141144 newm -> uuid = parent_module -> uuid ;
@@ -144,23 +147,27 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
144147 jl_register_root_module (newm );
145148 }
146149 else {
150+ newm -> parent = parent_module ;
147151 jl_binding_t * b = jl_get_binding_wr (parent_module , name , 1 );
148152 jl_declare_constant (b );
149- if (b -> value != NULL ) {
150- if (!jl_is_module (b -> value )) {
153+ jl_value_t * old = jl_atomic_compare_exchange (& b -> value , NULL , (jl_value_t * )newm );
154+ if (old != NULL ) {
155+ if (!jl_is_module (old )) {
151156 jl_errorf ("invalid redefinition of constant %s" , jl_symbol_name (name ));
152157 }
153- if (jl_generating_output ()) {
158+ if (jl_generating_output ())
154159 jl_errorf ("cannot replace module %s during compilation" , jl_symbol_name (name ));
155- }
156160 jl_printf (JL_STDERR , "WARNING: replacing module %s.\n" , jl_symbol_name (name ));
161+ old = jl_atomic_exchange (& b -> value , (jl_value_t * )newm );
162+ }
163+ jl_gc_wb_binding (b , newm );
164+ if (old != NULL ) {
157165 // create a hidden gc root for the old module
158- uintptr_t * refcnt = (uintptr_t * )ptrhash_bp (& jl_current_modules , (void * )b -> value );
166+ JL_LOCK (& jl_modules_mutex );
167+ uintptr_t * refcnt = (uintptr_t * )ptrhash_bp (& jl_current_modules , (void * )old );
159168 * refcnt += 1 ;
169+ JL_UNLOCK (& jl_modules_mutex );
160170 }
161- newm -> parent = parent_module ;
162- b -> value = (jl_value_t * )newm ;
163- jl_gc_wb_binding (b , newm );
164171 }
165172
166173 if (parent_module == jl_main_module && name == jl_symbol ("Base" )) {
@@ -213,6 +220,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
213220 }
214221#endif
215222
223+ JL_LOCK (& jl_modules_mutex );
216224 uintptr_t * refcnt = (uintptr_t * )ptrhash_bp (& jl_current_modules , (void * )newm );
217225 assert (* refcnt > (uintptr_t )HT_NOTFOUND );
218226 * refcnt -= 1 ;
@@ -225,6 +233,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
225233 // defer init of children until parent is done being defined
226234 // then initialize all in definition-finished order
227235 // at build time, don't run them at all (defer for runtime)
236+ form = NULL ;
228237 if (!jl_generating_output ()) {
229238 if (!ptrhash_has (& jl_current_modules , (void * )newm -> parent )) {
230239 size_t i , l = jl_array_len (jl_module_init_order );
@@ -241,12 +250,16 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
241250 }
242251 if (ns < l )
243252 jl_array_del_end (jl_module_init_order , l - ns );
244- l = jl_array_len (form );
245- for (i = 0 ; i < l ; i ++ ) {
246- jl_module_t * m = (jl_module_t * )jl_array_ptr_ref (form , i );
247- JL_GC_PROMISE_ROOTED (m );
248- jl_module_run_initializer (m );
249- }
253+ }
254+ }
255+ JL_UNLOCK (& jl_modules_mutex );
256+
257+ if (form ) {
258+ size_t i , l = jl_array_len (form );
259+ for (i = 0 ; i < l ; i ++ ) {
260+ jl_module_t * m = (jl_module_t * )jl_array_ptr_ref (form , i );
261+ JL_GC_PROMISE_ROOTED (m );
262+ jl_module_run_initializer (m );
250263 }
251264 }
252265
@@ -840,8 +853,11 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v)
840853void jl_check_open_for (jl_module_t * m , const char * funcname )
841854{
842855 if (jl_options .incremental && jl_generating_output ()) {
843- if (!ptrhash_has (& jl_current_modules , (void * )m ) && !jl_is__toplevel__mod (m )) {
844- if (m != jl_main_module ) { // TODO: this was grand-fathered in
856+ if (m != jl_main_module ) { // TODO: this was grand-fathered in
857+ JL_LOCK (& jl_modules_mutex );
858+ int open = ptrhash_has (& jl_current_modules , (void * )m );
859+ JL_UNLOCK (& jl_modules_mutex );
860+ if (!open && !jl_is__toplevel__mod (m )) {
845861 const char * name = jl_symbol_name (m -> name );
846862 jl_errorf ("Evaluation into the closed module `%s` breaks incremental compilation "
847863 "because the side effects will not be permanent. "
0 commit comments