@@ -1792,10 +1792,7 @@ end
1792
1792
# search for a precompile cache file to load, after some various checks
1793
1793
function _tryrequire_from_serialized (modkey:: PkgId , build_id:: UInt128 )
1794
1794
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 )
1799
1796
if loaded === nothing
1800
1797
try
1801
1798
modpath = locate_package (modkey)
@@ -1898,7 +1895,7 @@ end
1898
1895
continue
1899
1896
end
1900
1897
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}
1902
1899
# finish checking staledeps module graph
1903
1900
for i in 1 : length (staledeps)
1904
1901
dep = staledeps[i]
@@ -1918,7 +1915,7 @@ end
1918
1915
@goto check_next_path
1919
1916
@label check_next_dep
1920
1917
end
1921
- M = get (loaded_precompiles, pkg => build_id , nothing )
1918
+ M = get (loaded_precompiles, pkg => newbuild_id , nothing )
1922
1919
if isa (M, Module)
1923
1920
stalecheck && register_root_module (M)
1924
1921
return M
@@ -1931,15 +1928,12 @@ end
1931
1928
end
1932
1929
end
1933
1930
# 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
1934
1932
for i in 1 : length (staledeps)
1935
1933
dep = staledeps[i]
1936
1934
dep isa Module && continue
1937
1935
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)
1943
1937
while true
1944
1938
if dep isa Module
1945
1939
if PkgId (dep) == modkey && module_build_id (dep) === modbuild_id
@@ -1949,7 +1943,6 @@ end
1949
1943
@goto check_next_path
1950
1944
end
1951
1945
end
1952
- dep = start_loading (modkey)
1953
1946
if dep === nothing
1954
1947
try
1955
1948
set_pkgorigin_version_path (modkey, modpath)
@@ -1968,7 +1961,7 @@ end
1968
1961
end
1969
1962
staledeps[i] = dep
1970
1963
end
1971
- restored = get (loaded_precompiles, pkg => build_id , nothing )
1964
+ restored = get (loaded_precompiles, pkg => newbuild_id , nothing )
1972
1965
if ! isa (restored, Module)
1973
1966
restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps)
1974
1967
end
@@ -1992,11 +1985,17 @@ const package_locks = Dict{PkgId,Pair{Task,Threads.Condition}}()
1992
1985
1993
1986
debug_loading_deadlocks:: Bool = true # Enable a slightly more expensive, but more complete algorithm that can handle simultaneous tasks.
1994
1987
# 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
1998
1991
assert_havelock (require_lock)
1999
1992
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
2000
1999
loading = get (package_locks, modkey, nothing )
2001
2000
if loading === nothing
2002
2001
package_locks[modkey] = current_task () => Threads. Condition (require_lock)
@@ -2040,8 +2039,8 @@ function start_loading(modkey::PkgId)
2040
2039
end
2041
2040
throw (ConcurrencyViolationError (msg))
2042
2041
end
2043
- loading = wait (cond)
2044
- loading isa Module && return loading
2042
+ loaded = wait (cond)
2043
+ loaded isa Module && return loaded
2045
2044
end
2046
2045
end
2047
2046
@@ -2138,6 +2137,7 @@ order to throw an error if Julia attempts to precompile it.
2138
2137
end
2139
2138
2140
2139
# require always works in Main scope and loads files from node 1
2140
+ # XXX : (this is deprecated, but still used by Distributed)
2141
2141
const toplevel_load = Ref (true )
2142
2142
2143
2143
const _require_world_age = Ref {UInt} (typemax (UInt))
@@ -2284,24 +2284,28 @@ end
2284
2284
2285
2285
function __require_prelocked (uuidkey:: PkgId , env= nothing )
2286
2286
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)
2292
2300
end
2293
2301
insert_extension_triggers (uuidkey)
2294
2302
# After successfully loading, notify downstream consumers
2295
2303
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)
2303
2307
end
2304
- return newm
2308
+ return m
2305
2309
end
2306
2310
2307
2311
mutable struct PkgOrigin
@@ -2371,6 +2375,8 @@ maybe_root_module(key::PkgId) = @lock require_lock get(loaded_modules, key, noth
2371
2375
root_module_exists (key:: PkgId ) = @lock require_lock haskey (loaded_modules, key)
2372
2376
loaded_modules_array () = @lock require_lock copy (loaded_modules_order)
2373
2377
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))
2374
2380
function unreference_module (key:: PkgId )
2375
2381
if haskey (explicit_loaded_modules, key)
2376
2382
m = pop! (explicit_loaded_modules, key)
@@ -2401,119 +2407,110 @@ disable_parallel_precompile::Bool = false
2401
2407
# Returns `nothing` or the new(ish) module
2402
2408
function _require (pkg:: PkgId , env= nothing )
2403
2409
assert_havelock (require_lock)
2404
- loaded = start_loading (pkg)
2405
- loaded === nothing || return loaded
2406
2410
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 ())
2445
2445
end
2446
2446
end
2447
+ end
2447
2448
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)
2468
2460
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
2480
2477
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
2488
2479
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
2492
2488
end
2493
2489
end
2490
+ if JLOptions (). incremental != 0
2491
+ # during incremental precompilation, this should be fail-fast
2492
+ throw (PrecompilableError ())
2493
+ end
2494
2494
end
2495
+ end
2495
2496
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)
2501
2511
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)
2513
2513
end
2514
- finally
2515
- toplevel_load[] = last
2516
- end_loading (pkg, loaded)
2517
2514
end
2518
2515
return loaded
2519
2516
end
@@ -2536,8 +2533,9 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
2536
2533
@lock require_lock begin
2537
2534
# the PkgId of the ext, or package if not an ext
2538
2535
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
2541
2539
end
2542
2540
# first since this is a stdlib, try to look there directly first
2543
2541
env = Sys. STDLIB
@@ -2564,7 +2562,7 @@ function require_stdlib(package_uuidkey::PkgId, ext::Union{Nothing, String}=noth
2564
2562
# end
2565
2563
set_pkgorigin_version_path (this_uuidkey, sourcepath)
2566
2564
depot_path = append_bundled_depot_path! (empty (DEPOT_PATH ))
2567
- newm = start_loading (this_uuidkey)
2565
+ newm = start_loading (this_uuidkey, UInt128 ( 0 ), true )
2568
2566
newm === nothing || return newm
2569
2567
try
2570
2568
newm = _require_search_from_serialized (this_uuidkey, sourcepath, UInt128 (0 ), false ; DEPOT_PATH = depot_path)
0 commit comments