@@ -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,29 @@ 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 " )
2292- end
2293- insert_extension_triggers (uuidkey)
2294- # After successfully loading, notify downstream consumers
2295- 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
2287+ m = start_loading (uuidkey, UInt128 ( 0 ), true )
2288+ if m === nothing
2289+ last = toplevel_load[]
2290+ try
2291+ toplevel_load[] = false
2292+ newm = _require (uuidkey, env)
2293+ if newm === 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+ m = newm :: Module
2298+ insert_extension_triggers ( uuidkey)
2299+ # After successfully loading, notify downstream consumers
23002300 run_package_callbacks (uuidkey)
2301+ finally
2302+ toplevel_load[] = last
2303+ end_loading (uuidkey, m)
23012304 end
2302- newm = root_module (uuidkey)
2305+ elseif ! haskey (explicit_loaded_modules, uuidkey)
2306+ explicit_loaded_modules[uuidkey] = m
2307+ run_package_callbacks (uuidkey)
23032308 end
2304- return newm
2309+ return m
23052310end
23062311
23072312mutable struct PkgOrigin
@@ -2371,6 +2376,8 @@ maybe_root_module(key::PkgId) = @lock require_lock get(loaded_modules, key, noth
23712376root_module_exists (key:: PkgId ) = @lock require_lock haskey (loaded_modules, key)
23722377loaded_modules_array () = @lock require_lock copy (loaded_modules_order)
23732378
2379+ # after unreference_module, a subsequent require call will try to load a new copy of it, if stale
2380+ # reload(m) = (unreference_module(m); require(m))
23742381function unreference_module (key:: PkgId )
23752382 if haskey (explicit_loaded_modules, key)
23762383 m = pop! (explicit_loaded_modules, key)
@@ -2401,119 +2408,110 @@ disable_parallel_precompile::Bool = false
24012408# Returns `nothing` or the new(ish) module
24022409function _require (pkg:: PkgId , env= nothing )
24032410 assert_havelock (require_lock)
2404- loaded = start_loading (pkg)
2405- loaded === nothing || return loaded
24062411
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
2412+ # perform the search operation to select the module file require intends to load
2413+ path = locate_package (pkg, env)
2414+ if path === nothing
2415+ throw (ArgumentError ("""
2416+ Package $(repr (" text/plain" , pkg)) is required but does not seem to be installed:
2417+ - Run `Pkg.instantiate()` to install all recorded dependencies.
2418+ """ ))
2419+ end
2420+ set_pkgorigin_version_path (pkg, path)
2421+
2422+ parallel_precompile_attempted = false # being safe to avoid getting stuck in a precompilepkgs loop
2423+ reasons = Dict {String,Int} ()
2424+ # attempt to load the module file via the precompile cache locations
2425+ if JLOptions (). use_compiled_modules != 0
2426+ @label load_from_cache
2427+ loaded = _require_search_from_serialized (pkg, path, UInt128 (0 ), true ; reasons)
2428+ if loaded isa Module
2429+ return loaded
2430+ end
2431+ end
2432+
2433+ if JLOptions (). use_compiled_modules == 3
2434+ error (" Precompiled image $pkg not available with flags $(CacheFlags ()) " )
2435+ end
2436+
2437+ # if the module being required was supposed to have a particular version
2438+ # but it was not handled by the precompile loader, complain
2439+ for (concrete_pkg, concrete_build_id) in _concrete_dependencies
2440+ if pkg == concrete_pkg
2441+ @warn """ Module $(pkg. name) with build ID $((UUID (concrete_build_id))) is missing from the cache.
2442+ This may mean $(repr (" text/plain" , pkg)) does not support precompilation but is imported by a module that does."""
2443+ if JLOptions (). incremental != 0
2444+ # during incremental precompilation, this should be fail-fast
2445+ throw (PrecompilableError ())
24452446 end
24462447 end
2448+ end
24472449
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)
2450+ if JLOptions (). use_compiled_modules == 1
2451+ if ! generating_output (#= incremental=# false )
2452+ project = active_project ()
2453+ if ! generating_output () && ! parallel_precompile_attempted && ! disable_parallel_precompile && @isdefined (Precompilation) && project != = nothing &&
2454+ isfile (project) && project_file_manifest_path (project) != = nothing
2455+ parallel_precompile_attempted = true
2456+ unlock (require_lock)
2457+ try
2458+ Precompilation. precompilepkgs ([pkg. name]; _from_loading= true )
2459+ finally
2460+ lock (require_lock)
24682461 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
2462+ @goto load_from_cache
2463+ end
2464+ # spawn off a new incremental pre-compile task for recursive `require` calls
2465+ loaded = maybe_cachefile_lock (pkg, path) do
2466+ # double-check the search now that we have lock
2467+ m = _require_search_from_serialized (pkg, path, UInt128 (0 ), true )
2468+ m isa Module && return m
2469+ return compilecache (pkg, path; reasons)
2470+ end
2471+ loaded isa Module && return loaded
2472+ if isnothing (loaded) # maybe_cachefile_lock returns nothing if it had to wait for another process
2473+ @goto load_from_cache # the new cachefile will have the newest mtime so will come first in the search
2474+ elseif isa (loaded, Exception)
2475+ if precompilableerror (loaded)
2476+ verbosity = isinteractive () ? CoreLogging. Info : CoreLogging. Debug
2477+ @logmsg verbosity " Skipping precompilation due to precompilable error. Importing $(repr (" text/plain" , pkg)) ." exception= loaded
24802478 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
2479+ @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
24882480 end
2489- if JLOptions (). incremental != 0
2490- # during incremental precompilation, this should be fail-fast
2491- throw (PrecompilableError ())
2481+ # fall-through to loading the file locally if not incremental
2482+ else
2483+ cachefile, ocachefile = loaded:: Tuple{String, Union{Nothing, String}}
2484+ loaded = _tryrequire_from_serialized (pkg, cachefile, ocachefile)
2485+ if ! isa (loaded, Module)
2486+ @warn " The call to compilecache failed to create a usable precompiled cache file for $(repr (" text/plain" , pkg)) " exception= loaded
2487+ else
2488+ return loaded
24922489 end
24932490 end
2491+ if JLOptions (). incremental != 0
2492+ # during incremental precompilation, this should be fail-fast
2493+ throw (PrecompilableError ())
2494+ end
24942495 end
2496+ end
24952497
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__)
2498+ # just load the file normally via include
2499+ # for unknown dependencies
2500+ uuid = pkg. uuid
2501+ uuid = (uuid === nothing ? (UInt64 (0 ), UInt64 (0 )) : convert (NTuple{2 , UInt64}, uuid))
2502+ old_uuid = ccall (:jl_module_uuid , NTuple{2 , UInt64}, (Any,), __toplevel__)
2503+ if uuid != = old_uuid
2504+ ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, uuid)
2505+ end
2506+ unlock (require_lock)
2507+ try
2508+ include (__toplevel__, path)
2509+ loaded = get (loaded_modules, pkg, nothing )
2510+ finally
2511+ lock (require_lock)
25012512 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
2513+ ccall (:jl_set_module_uuid , Cvoid, (Any, NTuple{2 , UInt64}), __toplevel__, old_uuid)
25132514 end
2514- finally
2515- toplevel_load[] = last
2516- end_loading (pkg, loaded)
25172515 end
25182516 return loaded
25192517end
@@ -2536,8 +2534,9 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
25362534 @lock require_lock begin
25372535 # the PkgId of the ext, or package if not an ext
25382536 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]
2537+ newm = maybe_root_module (this_uuidkey)
2538+ if newm isa Module
2539+ return newm
25412540 end
25422541 # first since this is a stdlib, try to look there directly first
25432542 env = Sys. STDLIB
@@ -2564,7 +2563,7 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
25642563 # end
25652564 set_pkgorigin_version_path (this_uuidkey, sourcepath)
25662565 depot_path = append_bundled_depot_path! (empty (DEPOT_PATH ))
2567- newm = start_loading (this_uuidkey)
2566+ newm = start_loading (this_uuidkey, UInt128 ( 0 ), true )
25682567 newm === nothing || return newm
25692568 try
25702569 newm = _require_search_from_serialized (this_uuidkey, sourcepath, UInt128 (0 ), false ; DEPOT_PATH = depot_path)
0 commit comments