@@ -1792,10 +1792,7 @@ end
17921792# search for a precompile cache file to load, after some various checks
17931793function _tryrequire_from_serialized (modkey:: PkgId , build_id:: UInt128 )
17941794 assert_havelock (require_lock)
1795- loaded = maybe_root_module (modkey)
1796- if loaded === nothing
1797- loaded = start_loading (modkey)
1798- end
1795+ loaded = start_loading (modkey, build_id, false )
17991796 if loaded === nothing
18001797 try
18011798 modpath = locate_package (modkey)
@@ -1898,7 +1895,7 @@ end
18981895 continue
18991896 end
19001897 try
1901- staledeps, ocachefile, build_id = staledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
1898+ staledeps, ocachefile, newbuild_id = staledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
19021899 # finish checking staledeps module graph
19031900 for i in 1 : length (staledeps)
19041901 dep = staledeps[i]
@@ -1918,7 +1915,7 @@ end
19181915 @goto check_next_path
19191916 @label check_next_dep
19201917 end
1921- M = get (loaded_precompiles, pkg => build_id , nothing )
1918+ M = get (loaded_precompiles, pkg => newbuild_id , nothing )
19221919 if isa (M, Module)
19231920 stalecheck && register_root_module (M)
19241921 return M
@@ -1931,15 +1928,12 @@ end
19311928 end
19321929 end
19331930 # finish loading module graph into staledeps
1931+ # TODO : call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock
19341932 for i in 1 : length (staledeps)
19351933 dep = staledeps[i]
19361934 dep isa Module && continue
19371935 modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep:: Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}}
1938- if stalecheck
1939- dep = maybe_root_module (modkey)
1940- else
1941- dep = get (loaded_precompiles, modkey => modbuild_id, nothing )
1942- end
1936+ dep = start_loading (modkey, modbuild_id, stalecheck)
19431937 while true
19441938 if dep isa Module
19451939 if PkgId (dep) == modkey && module_build_id (dep) === modbuild_id
@@ -1949,7 +1943,6 @@ end
19491943 @goto check_next_path
19501944 end
19511945 end
1952- dep = start_loading (modkey)
19531946 if dep === nothing
19541947 try
19551948 set_pkgorigin_version_path (modkey, modpath)
@@ -1968,7 +1961,7 @@ end
19681961 end
19691962 staledeps[i] = dep
19701963 end
1971- restored = get (loaded_precompiles, pkg => build_id , nothing )
1964+ restored = get (loaded_precompiles, pkg => newbuild_id , nothing )
19721965 if ! isa (restored, Module)
19731966 restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps)
19741967 end
@@ -1992,11 +1985,17 @@ const package_locks = Dict{PkgId,Pair{Task,Threads.Condition}}()
19921985
19931986debug_loading_deadlocks:: Bool = true # Enable a slightly more expensive, but more complete algorithm that can handle simultaneous tasks.
19941987 # This only triggers if you have multiple tasks trying to load the same package at the same time,
1995- # so it is unlikely to make a difference normally.
1996- function start_loading (modkey:: PkgId )
1997- # handle recursive calls to require
1988+ # so it is unlikely to make a performance difference normally.
1989+ function start_loading (modkey:: PkgId , build_id :: UInt128 , stalecheck :: Bool )
1990+ # handle recursive and concurrent calls to require
19981991 assert_havelock (require_lock)
19991992 while true
1993+ loaded = stalecheck ? maybe_root_module (modkey) : nothing
1994+ loaded isa Module && return loaded
1995+ if build_id != UInt128 (0 )
1996+ loaded = get (loaded_precompiles, modkey => build_id, nothing )
1997+ loaded isa Module && return loaded
1998+ end
20001999 loading = get (package_locks, modkey, nothing )
20012000 if loading === nothing
20022001 package_locks[modkey] = current_task () => Threads. Condition (require_lock)
@@ -2040,8 +2039,8 @@ function start_loading(modkey::PkgId)
20402039 end
20412040 throw (ConcurrencyViolationError (msg))
20422041 end
2043- loading = wait (cond)
2044- loading isa Module && return loading
2042+ loaded = wait (cond)
2043+ loaded isa Module && return loaded
20452044 end
20462045end
20472046
@@ -2138,6 +2137,7 @@ order to throw an error if Julia attempts to precompile it.
21382137end
21392138
21402139# require always works in Main scope and loads files from node 1
2140+ # XXX : (this is deprecated, but still used by Distributed)
21412141const toplevel_load = Ref (true )
21422142
21432143const _require_world_age = Ref {UInt} (typemax (UInt))
@@ -2284,24 +2284,28 @@ end
22842284
22852285function __require_prelocked (uuidkey:: PkgId , env= nothing )
22862286 assert_havelock (require_lock)
2287- if ! root_module_exists (uuidkey)
2288- newm = _require (uuidkey, env)
2289- if newm === nothing
2290- error (" package `$(uuidkey. name) ` did not define the expected \
2291- module `$(uuidkey. name) `, check for typos in package module name" )
2287+ m = start_loading (uuidkey, UInt128 (0 ), true )
2288+ if m === nothing
2289+ last = toplevel_load[]
2290+ try
2291+ toplevel_load[] = false
2292+ m = _require (uuidkey, env)
2293+ if m === nothing
2294+ error (" package `$(uuidkey. name) ` did not define the expected \
2295+ module `$(uuidkey. name) `, check for typos in package module name" )
2296+ end
2297+ finally
2298+ toplevel_load[] = last
2299+ end_loading (uuidkey, m)
22922300 end
22932301 insert_extension_triggers (uuidkey)
22942302 # After successfully loading, notify downstream consumers
22952303 run_package_callbacks (uuidkey)
2296- else
2297- m = get (loaded_modules, uuidkey, nothing )
2298- if m != = nothing && ! haskey (explicit_loaded_modules, uuidkey)
2299- explicit_loaded_modules[uuidkey] = m
2300- run_package_callbacks (uuidkey)
2301- end
2302- newm = root_module (uuidkey)
2304+ elseif ! haskey (explicit_loaded_modules, uuidkey)
2305+ explicit_loaded_modules[uuidkey] = m
2306+ run_package_callbacks (uuidkey)
23032307 end
2304- return newm
2308+ return m
23052309end
23062310
23072311mutable struct PkgOrigin
@@ -2371,6 +2375,8 @@ maybe_root_module(key::PkgId) = @lock require_lock get(loaded_modules, key, noth
23712375root_module_exists (key:: PkgId ) = @lock require_lock haskey (loaded_modules, key)
23722376loaded_modules_array () = @lock require_lock copy (loaded_modules_order)
23732377
2378+ # after unreference_module, a subsequent require call will try to load a new copy of it, if stale
2379+ # reload(m) = (unreference_module(m); require(m))
23742380function unreference_module (key:: PkgId )
23752381 if haskey (explicit_loaded_modules, key)
23762382 m = pop! (explicit_loaded_modules, key)
@@ -2401,119 +2407,110 @@ disable_parallel_precompile::Bool = false
24012407# Returns `nothing` or the new(ish) module
24022408function _require (pkg:: PkgId , env= nothing )
24032409 assert_havelock (require_lock)
2404- loaded = start_loading (pkg)
2405- loaded === nothing || return loaded
24062410
2407- last = toplevel_load[]
2408- try
2409- toplevel_load[] = false
2410- # perform the search operation to select the module file require intends to load
2411- path = locate_package (pkg, env)
2412- if path === nothing
2413- throw (ArgumentError ("""
2414- Package $(repr (" text/plain" , pkg)) is required but does not seem to be installed:
2415- - Run `Pkg.instantiate()` to install all recorded dependencies.
2416- """ ))
2417- end
2418- set_pkgorigin_version_path (pkg, path)
2419-
2420- parallel_precompile_attempted = false # being safe to avoid getting stuck in a precompilepkgs loop
2421- reasons = Dict {String,Int} ()
2422- # attempt to load the module file via the precompile cache locations
2423- if JLOptions (). use_compiled_modules != 0
2424- @label load_from_cache
2425- loaded = _require_search_from_serialized (pkg, path, UInt128 (0 ), true ; reasons)
2426- if loaded isa Module
2427- return loaded
2428- end
2429- end
2430-
2431- if JLOptions (). use_compiled_modules == 3
2432- error (" Precompiled image $pkg not available with flags $(CacheFlags ()) " )
2433- end
2434-
2435- # if the module being required was supposed to have a particular version
2436- # but it was not handled by the precompile loader, complain
2437- for (concrete_pkg, concrete_build_id) in _concrete_dependencies
2438- if pkg == concrete_pkg
2439- @warn """ Module $(pkg. name) with build ID $((UUID (concrete_build_id))) is missing from the cache.
2440- This may mean $(repr (" text/plain" , pkg)) does not support precompilation but is imported by a module that does."""
2441- if JLOptions (). incremental != 0
2442- # during incremental precompilation, this should be fail-fast
2443- throw (PrecompilableError ())
2444- end
2411+ # perform the search operation to select the module file require intends to load
2412+ path = locate_package (pkg, env)
2413+ if path === nothing
2414+ throw (ArgumentError ("""
2415+ Package $(repr (" text/plain" , pkg)) is required but does not seem to be installed:
2416+ - Run `Pkg.instantiate()` to install all recorded dependencies.
2417+ """ ))
2418+ end
2419+ set_pkgorigin_version_path (pkg, path)
2420+
2421+ parallel_precompile_attempted = false # being safe to avoid getting stuck in a precompilepkgs loop
2422+ reasons = Dict {String,Int} ()
2423+ # attempt to load the module file via the precompile cache locations
2424+ if JLOptions (). use_compiled_modules != 0
2425+ @label load_from_cache
2426+ loaded = _require_search_from_serialized (pkg, path, UInt128 (0 ), true ; reasons)
2427+ if loaded isa Module
2428+ return loaded
2429+ end
2430+ end
2431+
2432+ if JLOptions (). use_compiled_modules == 3
2433+ error (" Precompiled image $pkg not available with flags $(CacheFlags ()) " )
2434+ end
2435+
2436+ # if the module being required was supposed to have a particular version
2437+ # but it was not handled by the precompile loader, complain
2438+ for (concrete_pkg, concrete_build_id) in _concrete_dependencies
2439+ if pkg == concrete_pkg
2440+ @warn """ Module $(pkg. name) with build ID $((UUID (concrete_build_id))) is missing from the cache.
2441+ This may mean $(repr (" text/plain" , pkg)) does not support precompilation but is imported by a module that does."""
2442+ if JLOptions (). incremental != 0
2443+ # during incremental precompilation, this should be fail-fast
2444+ throw (PrecompilableError ())
24452445 end
24462446 end
2447+ end
24472448
2448- if JLOptions (). use_compiled_modules == 1
2449- if ! generating_output (#= incremental=# false )
2450- project = active_project ()
2451- if ! generating_output () && ! parallel_precompile_attempted && ! disable_parallel_precompile && @isdefined (Precompilation) && project != = nothing &&
2452- isfile (project) && project_file_manifest_path (project) != = nothing
2453- parallel_precompile_attempted = true
2454- unlock (require_lock)
2455- try
2456- Precompilation. precompilepkgs ([pkg. name]; _from_loading= true )
2457- finally
2458- lock (require_lock)
2459- end
2460- @goto load_from_cache
2461- end
2462- # spawn off a new incremental pre-compile task for recursive `require` calls
2463- loaded = maybe_cachefile_lock (pkg, path) do
2464- # double-check the search now that we have lock
2465- m = _require_search_from_serialized (pkg, path, UInt128 (0 ), true )
2466- m isa Module && return m
2467- return compilecache (pkg, path; reasons)
2449+ if JLOptions (). use_compiled_modules == 1
2450+ if ! generating_output (#= incremental=# false )
2451+ project = active_project ()
2452+ if ! generating_output () && ! parallel_precompile_attempted && ! disable_parallel_precompile && @isdefined (Precompilation) && project != = nothing &&
2453+ isfile (project) && project_file_manifest_path (project) != = nothing
2454+ parallel_precompile_attempted = true
2455+ unlock (require_lock)
2456+ try
2457+ Precompilation. precompilepkgs ([pkg. name]; _from_loading= true )
2458+ finally
2459+ lock (require_lock)
24682460 end
2469- loaded isa Module && return loaded
2470- if isnothing (loaded) # maybe_cachefile_lock returns nothing if it had to wait for another process
2471- @goto load_from_cache # the new cachefile will have the newest mtime so will come first in the search
2472- elseif isa (loaded, Exception)
2473- if precompilableerror (loaded)
2474- verbosity = isinteractive () ? CoreLogging. Info : CoreLogging. Debug
2475- @logmsg verbosity " Skipping precompilation due to precompilable error. Importing $(repr (" text/plain" , pkg)) ." exception= loaded
2476- else
2477- @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
2478- end
2479- # fall-through to loading the file locally if not incremental
2461+ @goto load_from_cache
2462+ end
2463+ # spawn off a new incremental pre-compile task for recursive `require` calls
2464+ loaded = maybe_cachefile_lock (pkg, path) do
2465+ # double-check the search now that we have lock
2466+ m = _require_search_from_serialized (pkg, path, UInt128 (0 ), true )
2467+ m isa Module && return m
2468+ return compilecache (pkg, path; reasons)
2469+ end
2470+ loaded isa Module && return loaded
2471+ if isnothing (loaded) # maybe_cachefile_lock returns nothing if it had to wait for another process
2472+ @goto load_from_cache # the new cachefile will have the newest mtime so will come first in the search
2473+ elseif isa (loaded, Exception)
2474+ if precompilableerror (loaded)
2475+ verbosity = isinteractive () ? CoreLogging. Info : CoreLogging. Debug
2476+ @logmsg verbosity " Skipping precompilation due to precompilable error. Importing $(repr (" text/plain" , pkg)) ." exception= loaded
24802477 else
2481- cachefile, ocachefile = loaded:: Tuple{String, Union{Nothing, String}}
2482- loaded = _tryrequire_from_serialized (pkg, cachefile, ocachefile)
2483- if ! isa (loaded, Module)
2484- @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
2485- else
2486- return loaded
2487- end
2478+ @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
24882479 end
2489- if JLOptions (). incremental != 0
2490- # during incremental precompilation, this should be fail-fast
2491- throw (PrecompilableError ())
2480+ # fall-through to loading the file locally if not incremental
2481+ else
2482+ cachefile, ocachefile = loaded:: Tuple{String, Union{Nothing, String}}
2483+ loaded = _tryrequire_from_serialized (pkg, cachefile, ocachefile)
2484+ if ! isa (loaded, Module)
2485+ @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
2486+ else
2487+ return loaded
24922488 end
24932489 end
2490+ if JLOptions (). incremental != 0
2491+ # during incremental precompilation, this should be fail-fast
2492+ throw (PrecompilableError ())
2493+ end
24942494 end
2495+ end
24952496
2496- # just load the file normally via include
2497- # for unknown dependencies
2498- uuid = pkg. uuid
2499- uuid = (uuid === nothing ? (UInt64 (0 ), UInt64 (0 )) : convert (NTuple{2 , UInt64}, uuid))
2500- old_uuid = ccall (:jl_module_uuid , NTuple{2 , UInt64}, (Any,), __toplevel__)
2497+ # just load the file normally via include
2498+ # for unknown dependencies
2499+ uuid = pkg. uuid
2500+ uuid = (uuid === nothing ? (UInt64 (0 ), UInt64 (0 )) : convert (NTuple{2 , UInt64}, uuid))
2501+ old_uuid = ccall (:jl_module_uuid , NTuple{2 , UInt64}, (Any,), __toplevel__)
2502+ if uuid != = old_uuid
2503+ ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, uuid)
2504+ end
2505+ unlock (require_lock)
2506+ try
2507+ include (__toplevel__, path)
2508+ loaded = get (loaded_modules, pkg, nothing )
2509+ finally
2510+ lock (require_lock)
25012511 if uuid != = old_uuid
2502- ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, uuid)
2503- end
2504- unlock (require_lock)
2505- try
2506- include (__toplevel__, path)
2507- loaded = get (loaded_modules, pkg, nothing )
2508- finally
2509- lock (require_lock)
2510- if uuid != = old_uuid
2511- ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, old_uuid)
2512- end
2512+ ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, old_uuid)
25132513 end
2514- finally
2515- toplevel_load[] = last
2516- end_loading (pkg, loaded)
25172514 end
25182515 return loaded
25192516end
@@ -2536,8 +2533,9 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
25362533 @lock require_lock begin
25372534 # the PkgId of the ext, or package if not an ext
25382535 this_uuidkey = ext isa String ? PkgId (uuid5 (package_uuidkey. uuid, ext), ext) : package_uuidkey
2539- if root_module_exists (this_uuidkey)
2540- return loaded_modules[this_uuidkey]
2536+ newm = maybe_root_module (this_uuidkey)
2537+ if newm isa Module
2538+ return newm
25412539 end
25422540 # first since this is a stdlib, try to look there directly first
25432541 env = Sys. STDLIB
@@ -2564,7 +2562,7 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
25642562 # end
25652563 set_pkgorigin_version_path (this_uuidkey, sourcepath)
25662564 depot_path = append_bundled_depot_path! (empty (DEPOT_PATH ))
2567- newm = start_loading (this_uuidkey)
2565+ newm = start_loading (this_uuidkey, UInt128 ( 0 ), true )
25682566 newm === nothing || return newm
25692567 try
25702568 newm = _require_search_from_serialized (this_uuidkey, sourcepath, UInt128 (0 ), false ; DEPOT_PATH = depot_path)
0 commit comments