@@ -1232,7 +1232,7 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No
12321232 dep = depmods[i]
12331233 dep isa Module && continue
12341234 _, depkey, depbuild_id = dep:: Tuple{String, PkgId, UInt128}
1235- dep = loaded_precompiles[ depkey => depbuild_id]
1235+ dep = something ( maybe_loaded_precompile ( depkey, depbuild_id))
12361236 @assert PkgId (dep) == depkey && module_build_id (dep) === depbuild_id
12371237 depmods[i] = dep
12381238 end
@@ -1338,6 +1338,7 @@ end
13381338
13391339function register_restored_modules (sv:: SimpleVector , pkg:: PkgId , path:: String )
13401340 # This function is also used by PkgCacheInspector.jl
1341+ assert_havelock (require_lock)
13411342 restored = sv[1 ]:: Vector{Any}
13421343 for M in restored
13431344 M = M:: Module
@@ -1346,7 +1347,7 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
13461347 end
13471348 if parentmodule (M) === M
13481349 push! (loaded_modules_order, M)
1349- loaded_precompiles[pkg => module_build_id (M)] = M
1350+ push! ( get! (Vector{Module}, loaded_precompiles, pkg), M)
13501351 end
13511352 end
13521353
@@ -1962,90 +1963,102 @@ end
19621963 assert_havelock (require_lock)
19631964 paths = find_all_in_cache_path (pkg, DEPOT_PATH )
19641965 newdeps = PkgId[]
1965- for path_to_try in paths:: Vector{String}
1966- staledeps = stale_cachefile (pkg, build_id, sourcepath, path_to_try; reasons, stalecheck)
1967- if staledeps === true
1968- continue
1969- end
1970- try
1971- staledeps, ocachefile, newbuild_id = staledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
1972- # finish checking staledeps module graph
1973- for i in eachindex (staledeps)
1974- dep = staledeps[i]
1975- dep isa Module && continue
1976- modpath, modkey, modbuild_id = dep:: Tuple{String, PkgId, UInt128}
1977- modpaths = find_all_in_cache_path (modkey, DEPOT_PATH )
1978- for modpath_to_try in modpaths
1979- modstaledeps = stale_cachefile (modkey, modbuild_id, modpath, modpath_to_try; stalecheck)
1980- if modstaledeps === true
1981- continue
1982- end
1983- modstaledeps, modocachepath, _ = modstaledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
1984- staledeps[i] = (modpath, modkey, modbuild_id, modpath_to_try, modstaledeps, modocachepath)
1985- @goto check_next_dep
1966+ try_build_ids = UInt128[build_id]
1967+ if build_id == UInt128 (0 )
1968+ let loaded = get (loaded_precompiles, pkg, nothing )
1969+ if loaded != = nothing
1970+ for mod in loaded # try these in reverse original load order to see if one is already valid
1971+ pushfirst! (try_build_ids, module_build_id (mod))
19861972 end
1987- @debug " Rejecting cache file $path_to_try because required dependency $modkey with build ID $(UUID (modbuild_id)) is missing from the cache."
1988- @goto check_next_path
1989- @label check_next_dep
19901973 end
1991- M = get (loaded_precompiles, pkg => newbuild_id, nothing )
1992- if isa (M, Module)
1993- stalecheck && register_root_module (M)
1994- return M
1995- end
1996- if stalecheck
1997- try
1998- touch (path_to_try) # update timestamp of precompilation file
1999- catch ex # file might be read-only and then we fail to update timestamp, which is fine
2000- ex isa IOError || rethrow ()
2001- end
1974+ end
1975+ end
1976+ for build_id in try_build_ids
1977+ for path_to_try in paths:: Vector{String}
1978+ staledeps = stale_cachefile (pkg, build_id, sourcepath, path_to_try; reasons, stalecheck)
1979+ if staledeps === true
1980+ continue
20021981 end
2003- # finish loading module graph into staledeps
2004- # TODO : call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock
2005- for i in eachindex (staledeps)
2006- dep = staledeps[i]
2007- dep isa Module && continue
2008- modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep:: Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}}
2009- dep = start_loading (modkey, modbuild_id, stalecheck)
2010- while true
2011- if dep isa Module
2012- if PkgId (dep) == modkey && module_build_id (dep) === modbuild_id
2013- break
2014- else
2015- @debug " Rejecting cache file $path_to_try because module $modkey got loaded at a different version than expected."
2016- @goto check_next_path
1982+ try
1983+ staledeps, ocachefile, newbuild_id = staledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
1984+ # finish checking staledeps module graph
1985+ for i in eachindex (staledeps)
1986+ dep = staledeps[i]
1987+ dep isa Module && continue
1988+ modpath, modkey, modbuild_id = dep:: Tuple{String, PkgId, UInt128}
1989+ modpaths = find_all_in_cache_path (modkey, DEPOT_PATH )
1990+ for modpath_to_try in modpaths
1991+ modstaledeps = stale_cachefile (modkey, modbuild_id, modpath, modpath_to_try; stalecheck)
1992+ if modstaledeps === true
1993+ continue
20171994 end
1995+ modstaledeps, modocachepath, _ = modstaledeps:: Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
1996+ staledeps[i] = (modpath, modkey, modbuild_id, modpath_to_try, modstaledeps, modocachepath)
1997+ @goto check_next_dep
20181998 end
2019- if dep === nothing
2020- try
2021- set_pkgorigin_version_path (modkey, modpath)
2022- dep = _include_from_serialized (modkey, modcachepath, modocachepath, modstaledeps; register = stalecheck)
2023- finally
2024- end_loading (modkey, dep)
1999+ @debug " Rejecting cache file $path_to_try because required dependency $modkey with build ID $(UUID (modbuild_id)) is missing from the cache."
2000+ @goto check_next_path
2001+ @label check_next_dep
2002+ end
2003+ M = maybe_loaded_precompile (pkg, newbuild_id)
2004+ if isa (M, Module)
2005+ stalecheck && register_root_module (M)
2006+ return M
2007+ end
2008+ if stalecheck
2009+ try
2010+ touch (path_to_try) # update timestamp of precompilation file
2011+ catch ex # file might be read-only and then we fail to update timestamp, which is fine
2012+ ex isa IOError || rethrow ()
2013+ end
2014+ end
2015+ # finish loading module graph into staledeps
2016+ # TODO : call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock
2017+ for i in eachindex (staledeps)
2018+ dep = staledeps[i]
2019+ dep isa Module && continue
2020+ modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep:: Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}}
2021+ dep = start_loading (modkey, modbuild_id, stalecheck)
2022+ while true
2023+ if dep isa Module
2024+ if PkgId (dep) == modkey && module_build_id (dep) === modbuild_id
2025+ break
2026+ else
2027+ @debug " Rejecting cache file $path_to_try because module $modkey got loaded at a different version than expected."
2028+ @goto check_next_path
2029+ end
20252030 end
2026- if ! isa (dep, Module)
2027- @debug " Rejecting cache file $path_to_try because required dependency $modkey failed to load from cache file for $modcachepath ." exception= dep
2028- @goto check_next_path
2029- else
2030- push! (newdeps, modkey)
2031+ if dep === nothing
2032+ try
2033+ set_pkgorigin_version_path (modkey, modpath)
2034+ dep = _include_from_serialized (modkey, modcachepath, modocachepath, modstaledeps; register = stalecheck)
2035+ finally
2036+ end_loading (modkey, dep)
2037+ end
2038+ if ! isa (dep, Module)
2039+ @debug " Rejecting cache file $path_to_try because required dependency $modkey failed to load from cache file for $modcachepath ." exception= dep
2040+ @goto check_next_path
2041+ else
2042+ push! (newdeps, modkey)
2043+ end
20312044 end
20322045 end
2046+ staledeps[i] = dep
20332047 end
2034- staledeps[i] = dep
2035- end
2036- restored = get (loaded_precompiles, pkg => newbuild_id, nothing )
2037- if ! isa (restored, Module)
2038- restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps; register = stalecheck)
2039- end
2040- isa (restored, Module) && return restored
2041- @debug " Deserialization checks failed while attempting to load cache from $path_to_try " exception = restored
2042- @label check_next_path
2043- finally
2044- for modkey in newdeps
2045- insert_extension_triggers (modkey)
2046- stalecheck && run_package_callbacks (modkey )
2048+ restored = maybe_loaded_precompile (pkg, newbuild_id)
2049+ if ! isa (restored, Module)
2050+ restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps; register = stalecheck )
2051+ end
2052+ isa (restored, Module) && return restored
2053+ @debug " Deserialization checks failed while attempting to load cache from $path_to_try " exception = restored
2054+ @label check_next_path
2055+ finally
2056+ for modkey in newdeps
2057+ insert_extension_triggers (modkey)
2058+ stalecheck && run_package_callbacks (modkey)
2059+ end
2060+ empty! (newdeps )
20472061 end
2048- empty! (newdeps)
20492062 end
20502063 end
20512064 return nothing
@@ -2065,7 +2078,7 @@ function start_loading(modkey::PkgId, build_id::UInt128, stalecheck::Bool)
20652078 loaded = stalecheck ? maybe_root_module (modkey) : nothing
20662079 loaded isa Module && return loaded
20672080 if build_id != UInt128 (0 )
2068- loaded = get (loaded_precompiles, modkey => build_id, nothing )
2081+ loaded = maybe_loaded_precompile ( modkey, build_id )
20692082 loaded isa Module && return loaded
20702083 end
20712084 loading = get (package_locks, modkey, nothing )
@@ -2394,13 +2407,22 @@ const pkgorigins = Dict{PkgId,PkgOrigin}()
23942407
23952408const explicit_loaded_modules = Dict {PkgId,Module} () # Emptied on Julia start
23962409const loaded_modules = Dict {PkgId,Module} () # available to be explicitly loaded
2397- const loaded_precompiles = Dict {Pair{ PkgId,UInt128}, Module} () # extended (complete) list of modules, available to be loaded
2410+ const loaded_precompiles = Dict {PkgId,Vector{ Module} } () # extended (complete) list of modules, available to be loaded
23982411const loaded_modules_order = Vector {Module} ()
23992412const module_keys = IdDict {Module,PkgId} () # the reverse of loaded_modules
24002413
24012414is_root_module (m:: Module ) = @lock require_lock haskey (module_keys, m)
24022415root_module_key (m:: Module ) = @lock require_lock module_keys[m]
24032416
2417+ function maybe_loaded_precompile (key:: PkgId , buildid:: UInt128 )
2418+ assert_havelock (require_lock)
2419+ mods = get (loaded_precompiles, key, nothing )
2420+ mods === nothing && return
2421+ for mod in mods
2422+ module_build_id (mod) == buildid && return mod
2423+ end
2424+ end
2425+
24042426function module_build_id (m:: Module )
24052427 hi, lo = ccall (:jl_module_build_id , NTuple{2 ,UInt64}, (Any,), m)
24062428 return (UInt128 (hi) << 64 ) | lo
@@ -2421,7 +2443,7 @@ end
24212443 end
24222444 end
24232445 end
2424- haskey (loaded_precompiles, key => module_build_id (m)) || push! (loaded_modules_order, m)
2446+ maybe_loaded_precompile (key, module_build_id (m)) === nothing && push! (loaded_modules_order, m)
24252447 loaded_modules[key] = m
24262448 explicit_loaded_modules[key] = m
24272449 module_keys[m] = key
@@ -3785,8 +3807,8 @@ end
37853807 for i in 1 : ndeps
37863808 req_key, req_build_id = required_modules[i]
37873809 # Check if module is already loaded
3788- if ! stalecheck && haskey (loaded_precompiles, req_key => req_build_id)
3789- M = loaded_precompiles[req_key => req_build_id]
3810+ M = stalecheck ? nothing : maybe_loaded_precompile (req_key, req_build_id)
3811+ if M != = nothing
37903812 @assert PkgId (M) == req_key && module_build_id (M) === req_build_id
37913813 depmods[i] = M
37923814 elseif root_module_exists (req_key)
0 commit comments