@@ -524,8 +524,7 @@ See also [`pkgdir`](@ref).
524
524
"""
525
525
function pathof (m:: Module )
526
526
@lock require_lock begin
527
- pkgid = get (module_keys, m, nothing )
528
- pkgid === nothing && return nothing
527
+ pkgid = PkgId (m)
529
528
origin = get (pkgorigins, pkgid, nothing )
530
529
origin === nothing && return nothing
531
530
path = origin. path
@@ -1652,7 +1651,7 @@ get_extension(parent::Module, ext::Symbol) = get_extension(PkgId(parent), ext)
1652
1651
function get_extension (parentid:: PkgId , ext:: Symbol )
1653
1652
parentid. uuid === nothing && return nothing
1654
1653
extid = PkgId (uuid5 (parentid. uuid, string (ext)), string (ext))
1655
- return get (loaded_modules, extid, nothing )
1654
+ return maybe_root_module ( extid)
1656
1655
end
1657
1656
1658
1657
# End extensions
@@ -1811,7 +1810,7 @@ function show(io::IO, it::ImageTarget)
1811
1810
end
1812
1811
1813
1812
# should sync with the types of arguments of `stale_cachefile`
1814
- const StaleCacheKey = Tuple{Base . PkgId, UInt128, String, String}
1813
+ const StaleCacheKey = Tuple{PkgId, UInt128, String, String}
1815
1814
1816
1815
function compilecache_path (pkg:: PkgId ;
1817
1816
ignore_loaded:: Bool = false ,
@@ -2063,7 +2062,7 @@ end
2063
2062
modpath, modkey, modbuild_id = dep:: Tuple{String, PkgId, UInt128}
2064
2063
# inline a call to start_loading here
2065
2064
@assert canstart_loading (modkey, modbuild_id, stalecheck) === nothing
2066
- package_locks[modkey] = current_task () => Threads. Condition (require_lock)
2065
+ package_locks[modkey] = ( current_task (), Threads. Condition (require_lock), modbuild_id )
2067
2066
startedloading = i
2068
2067
modpaths = find_all_in_cache_path (modkey, DEPOT_PATH )
2069
2068
for modpath_to_try in modpaths
@@ -2139,7 +2138,7 @@ end
2139
2138
end
2140
2139
2141
2140
# to synchronize multiple tasks trying to import/using something
2142
- const package_locks = Dict {PkgId,Pair {Task,Threads.Condition}} ()
2141
+ const package_locks = Dict {PkgId,Tuple {Task,Threads.Condition,UInt128 }} ()
2143
2142
2144
2143
debug_loading_deadlocks:: Bool = true # Enable a slightly more expensive, but more complete algorithm that can handle simultaneous tasks.
2145
2144
# This only triggers if you have multiple tasks trying to load the same package at the same time,
@@ -2148,14 +2147,21 @@ debug_loading_deadlocks::Bool = true # Enable a slightly more expensive, but mor
2148
2147
function canstart_loading (modkey:: PkgId , build_id:: UInt128 , stalecheck:: Bool )
2149
2148
assert_havelock (require_lock)
2150
2149
require_lock. reentrancy_cnt == 1 || throw (ConcurrencyViolationError (" recursive call to start_loading" ))
2151
- loaded = stalecheck ? maybe_root_module (modkey) : nothing
2152
- loaded isa Module && return loaded
2153
- if build_id != UInt128 (0 )
2150
+ loading = get (package_locks, modkey, nothing )
2151
+ if loading === nothing
2152
+ loaded = stalecheck ? maybe_root_module (modkey) : nothing
2153
+ loaded isa Module && return loaded
2154
+ if build_id != UInt128 (0 )
2155
+ loaded = maybe_loaded_precompile (modkey, build_id)
2156
+ loaded isa Module && return loaded
2157
+ end
2158
+ return nothing
2159
+ end
2160
+ if ! stalecheck && build_id != UInt128 (0 ) && loading[3 ] != build_id
2161
+ # don't block using an existing specific loaded module on needing a different concurrently loaded one
2154
2162
loaded = maybe_loaded_precompile (modkey, build_id)
2155
2163
loaded isa Module && return loaded
2156
2164
end
2157
- loading = get (package_locks, modkey, nothing )
2158
- loading === nothing && return nothing
2159
2165
# load already in progress for this module on the task
2160
2166
task, cond = loading
2161
2167
deps = String[modkey. name]
@@ -2202,7 +2208,7 @@ function start_loading(modkey::PkgId, build_id::UInt128, stalecheck::Bool)
2202
2208
while true
2203
2209
loaded = canstart_loading (modkey, build_id, stalecheck)
2204
2210
if loaded === nothing
2205
- package_locks[modkey] = current_task () => Threads. Condition (require_lock)
2211
+ package_locks[modkey] = ( current_task (), Threads. Condition (require_lock), build_id )
2206
2212
return nothing
2207
2213
elseif loaded isa Module
2208
2214
return loaded
@@ -2333,15 +2339,15 @@ For more details regarding code loading, see the manual sections on [modules](@r
2333
2339
[parallel computing](@ref code-availability).
2334
2340
"""
2335
2341
function require (into:: Module , mod:: Symbol )
2336
- if _require_world_age[] != typemax (UInt)
2337
- Base. invoke_in_world (_require_world_age[], __require, into, mod)
2338
- else
2339
- @invokelatest __require (into, mod)
2342
+ world = _require_world_age[]
2343
+ if world == typemax (UInt)
2344
+ world = get_world_counter ()
2340
2345
end
2346
+ return invoke_in_world (world, __require, into, mod)
2341
2347
end
2342
2348
2343
2349
function __require (into:: Module , mod:: Symbol )
2344
- if into === Base . __toplevel__ && generating_output (#= incremental=# true )
2350
+ if into === __toplevel__ && generating_output (#= incremental=# true )
2345
2351
error (" `using/import $mod ` outside of a Module detected. Importing a package outside of a module \
2346
2352
is not allowed during package precompilation." )
2347
2353
end
@@ -2445,24 +2451,22 @@ function collect_manifest_warnings()
2445
2451
return msg
2446
2452
end
2447
2453
2448
- require (uuidkey:: PkgId ) = @lock require_lock _require_prelocked (uuidkey)
2449
-
2450
- function _require_prelocked (uuidkey:: PkgId , env= nothing )
2451
- if _require_world_age[] != typemax (UInt)
2452
- Base. invoke_in_world (_require_world_age[], __require_prelocked, uuidkey, env)
2453
- else
2454
- @invokelatest __require_prelocked (uuidkey, env)
2454
+ function require (uuidkey:: PkgId )
2455
+ world = _require_world_age[]
2456
+ if world == typemax (UInt)
2457
+ world = get_world_counter ()
2455
2458
end
2459
+ return invoke_in_world (world, __require, uuidkey)
2456
2460
end
2457
-
2458
- function __require_prelocked (uuidkey:: PkgId , env= nothing )
2461
+ __require (uuidkey :: PkgId ) = @lock require_lock _require_prelocked (uuidkey)
2462
+ function _require_prelocked (uuidkey:: PkgId , env= nothing )
2459
2463
assert_havelock (require_lock)
2460
2464
m = start_loading (uuidkey, UInt128 (0 ), true )
2461
2465
if m === nothing
2462
2466
last = toplevel_load[]
2463
2467
try
2464
2468
toplevel_load[] = false
2465
- m = _require (uuidkey, env)
2469
+ m = __require_prelocked (uuidkey, env)
2466
2470
if m === nothing
2467
2471
error (" package `$(uuidkey. name) ` did not define the expected \
2468
2472
module `$(uuidkey. name) `, check for typos in package module name" )
@@ -2474,8 +2478,6 @@ function __require_prelocked(uuidkey::PkgId, env=nothing)
2474
2478
insert_extension_triggers (uuidkey)
2475
2479
# After successfully loading, notify downstream consumers
2476
2480
run_package_callbacks (uuidkey)
2477
- else
2478
- newm = root_module (uuidkey)
2479
2481
end
2480
2482
return m
2481
2483
end
@@ -2491,9 +2493,8 @@ const pkgorigins = Dict{PkgId,PkgOrigin}()
2491
2493
const loaded_modules = Dict {PkgId,Module} () # available to be explicitly loaded
2492
2494
const loaded_precompiles = Dict {PkgId,Vector{Module}} () # extended (complete) list of modules, available to be loaded
2493
2495
const loaded_modules_order = Vector {Module} ()
2494
- const module_keys = IdDict {Module,PkgId} () # the reverse of loaded_modules
2495
2496
2496
- root_module_key (m:: Module ) = @lock require_lock module_keys[m]
2497
+ root_module_key (m:: Module ) = PkgId (m)
2497
2498
2498
2499
function maybe_loaded_precompile (key:: PkgId , buildid:: UInt128 )
2499
2500
@lock require_lock begin
@@ -2527,7 +2528,6 @@ end
2527
2528
end
2528
2529
maybe_loaded_precompile (key, module_build_id (m)) === nothing && push! (loaded_modules_order, m)
2529
2530
loaded_modules[key] = m
2530
- module_keys[m] = key
2531
2531
end
2532
2532
nothing
2533
2533
end
@@ -2544,24 +2544,27 @@ using Base
2544
2544
end
2545
2545
2546
2546
# get a top-level Module from the given key
2547
+ # this is similar to `require`, but worse in almost every possible way
2547
2548
root_module (key:: PkgId ) = @lock require_lock loaded_modules[key]
2548
2549
function root_module (where :: Module , name:: Symbol )
2549
2550
key = identify_package (where , String (name))
2550
2551
key isa PkgId || throw (KeyError (name))
2551
2552
return root_module (key)
2552
2553
end
2554
+ root_module_exists (key:: PkgId ) = @lock require_lock haskey (loaded_modules, key)
2553
2555
maybe_root_module (key:: PkgId ) = @lock require_lock get (loaded_modules, key, nothing )
2554
2556
2555
- root_module_exists (key:: PkgId ) = @lock require_lock haskey (loaded_modules, key)
2556
2557
loaded_modules_array () = @lock require_lock copy (loaded_modules_order)
2557
2558
2558
2559
# after unreference_module, a subsequent require call will try to load a new copy of it, if stale
2559
2560
# reload(m) = (unreference_module(m); require(m))
2560
2561
function unreference_module (key:: PkgId )
2562
+ @lock require_lock begin
2561
2563
if haskey (loaded_modules, key)
2562
2564
m = pop! (loaded_modules, key)
2563
2565
# need to ensure all modules are GC rooted; will still be referenced
2564
- # in module_keys
2566
+ # in loaded_modules_order
2567
+ end
2565
2568
end
2566
2569
end
2567
2570
@@ -2582,7 +2585,7 @@ const PKG_PRECOMPILE_HOOK = Ref{Function}()
2582
2585
disable_parallel_precompile:: Bool = false
2583
2586
2584
2587
# Returns `nothing` or the new(ish) module
2585
- function _require (pkg:: PkgId , env= nothing )
2588
+ function __require_prelocked (pkg:: PkgId , env)
2586
2589
assert_havelock (require_lock)
2587
2590
2588
2591
# perform the search operation to select the module file require intends to load
@@ -2682,7 +2685,7 @@ function _require(pkg::PkgId, env=nothing)
2682
2685
unlock (require_lock)
2683
2686
try
2684
2687
include (__toplevel__, path)
2685
- loaded = get (loaded_modules, pkg, nothing )
2688
+ loaded = maybe_root_module ( pkg)
2686
2689
finally
2687
2690
lock (require_lock)
2688
2691
if uuid != = old_uuid
@@ -2755,38 +2758,18 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
2755
2758
@lock require_lock begin
2756
2759
# the PkgId of the ext, or package if not an ext
2757
2760
this_uuidkey = ext isa String ? PkgId (uuid5 (package_uuidkey. uuid, ext), ext) : package_uuidkey
2758
- newm = maybe_root_module (this_uuidkey)
2759
- if newm isa Module
2760
- return newm
2761
- end
2762
- # first since this is a stdlib, try to look there directly first
2763
2761
env = Sys. STDLIB
2764
- # sourcepath = ""
2765
- if ext === nothing
2766
- sourcepath = normpath (env, this_uuidkey. name, " src" , this_uuidkey. name * " .jl" )
2767
- else
2768
- sourcepath = find_ext_path (normpath (joinpath (env, package_uuidkey. name)), ext)
2769
- end
2770
- # mbypath = manifest_uuid_path(env, this_uuidkey)
2771
- # if mbypath isa String && isfile_casesensitive(mbypath)
2772
- # sourcepath = mbypath
2773
- # else
2774
- # # if the user deleted the stdlib folder, we next try using their environment
2775
- # sourcepath = locate_package_env(this_uuidkey)
2776
- # if sourcepath !== nothing
2777
- # sourcepath, env = sourcepath
2778
- # end
2779
- # end
2780
- # if sourcepath === nothing
2781
- # throw(ArgumentError("""
2782
- # Package $(repr("text/plain", this_uuidkey)) is required but does not seem to be installed.
2783
- # """))
2784
- # end
2785
- set_pkgorigin_version_path (this_uuidkey, sourcepath)
2786
- depot_path = append_bundled_depot_path! (empty (DEPOT_PATH ))
2787
2762
newm = start_loading (this_uuidkey, UInt128 (0 ), true )
2788
2763
newm === nothing || return newm
2789
2764
try
2765
+ # first since this is a stdlib, try to look there directly first
2766
+ if ext === nothing
2767
+ sourcepath = normpath (env, this_uuidkey. name, " src" , this_uuidkey. name * " .jl" )
2768
+ else
2769
+ sourcepath = find_ext_path (normpath (joinpath (env, package_uuidkey. name)), ext)
2770
+ end
2771
+ depot_path = append_bundled_depot_path! (empty (DEPOT_PATH ))
2772
+ set_pkgorigin_version_path (this_uuidkey, sourcepath)
2790
2773
newm = _require_search_from_serialized (this_uuidkey, sourcepath, UInt128 (0 ), false ; DEPOT_PATH = depot_path)
2791
2774
finally
2792
2775
end_loading (this_uuidkey, newm)
@@ -3968,32 +3951,32 @@ end
3968
3951
if M != = nothing
3969
3952
@assert PkgId (M) == req_key && module_build_id (M) === req_build_id
3970
3953
depmods[i] = M
3971
- elseif root_module_exists (req_key)
3972
- M = root_module (req_key)
3954
+ continue
3955
+ end
3956
+ M = maybe_root_module (req_key)
3957
+ if M isa Module
3973
3958
if PkgId (M) == req_key && module_build_id (M) === req_build_id
3974
3959
depmods[i] = M
3960
+ continue
3975
3961
elseif M == Core
3976
3962
@debug " Rejecting cache file $cachefile because it was made with a different julia version"
3977
3963
record_reason (reasons, " wrong julia version" )
3978
3964
return true # Won't be able to fulfill dependency
3979
3965
elseif ignore_loaded || ! stalecheck
3980
3966
# Used by Pkg.precompile given that there it's ok to precompile different versions of loaded packages
3981
- @goto locate_branch
3982
3967
else
3983
3968
@debug " Rejecting cache file $cachefile because module $req_key is already loaded and incompatible."
3984
3969
record_reason (reasons, " wrong dep version loaded" )
3985
3970
return true # Won't be able to fulfill dependency
3986
3971
end
3987
- else
3988
- @label locate_branch
3989
- path = locate_package (req_key) # TODO : add env and/or skip this when stalecheck is false
3990
- if path === nothing
3991
- @debug " Rejecting cache file $cachefile because dependency $req_key not found."
3992
- record_reason (reasons, " dep missing source" )
3993
- return true # Won't be able to fulfill dependency
3994
- end
3995
- depmods[i] = (path, req_key, req_build_id)
3996
3972
end
3973
+ path = locate_package (req_key) # TODO : add env and/or skip this when stalecheck is false
3974
+ if path === nothing
3975
+ @debug " Rejecting cache file $cachefile because dependency $req_key not found."
3976
+ record_reason (reasons, " dep missing source" )
3977
+ return true # Won't be able to fulfill dependency
3978
+ end
3979
+ depmods[i] = (path, req_key, req_build_id)
3997
3980
end
3998
3981
3999
3982
# check if this file is going to provide one of our concrete dependencies
0 commit comments