@@ -118,22 +118,58 @@ end
118
118
119
119
# these return either the array of modules loaded from the path / content given
120
120
# or an Exception that describes why it couldn't be loaded
121
- function _include_from_serialized (content:: Vector{UInt8} )
122
- return ccall (:jl_restore_incremental_from_buf , Any, (Ptr{UInt8}, Int), content, sizeof (content))
121
+ function _include_from_serialized (content:: Vector{UInt8} , depmods :: Vector{Module} )
122
+ return ccall (:jl_restore_incremental_from_buf , Any, (Ptr{UInt8}, Int, Any ), content, sizeof (content), depmods )
123
123
end
124
- function _include_from_serialized (path:: String )
125
- return ccall (:jl_restore_incremental , Any, (Cstring,), path)
124
+ function _include_from_serialized (path:: String , depmods :: Vector{Module} )
125
+ return ccall (:jl_restore_incremental , Any, (Cstring, Any ), path, depmods )
126
126
end
127
127
128
128
# returns an array of modules loaded, or an Exception that describes why it failed
129
129
# and it reconnects the Base.Docs.META
130
130
function _require_from_serialized (mod:: Symbol , path_to_try:: String )
131
- restored = _include_from_serialized (path_to_try)
131
+ return _require_from_serialized (mod, path_to_try, parse_cache_header (path_to_try)[3 ])
132
+ end
133
+ function _require_from_serialized (mod:: Symbol , path_to_try:: String , depmodnames:: Vector{Pair{Symbol, UInt64}} )
134
+ # load all of the dependent modules
135
+ ndeps = length (depmodnames)
136
+ depmods = Vector {Module} (uninitialized, ndeps)
137
+ for i in 1 : ndeps
138
+ modname, uuid = depmodnames[i]
139
+ if root_module_exists (modname)
140
+ M = root_module (modname)
141
+ if module_name (M) === modname && module_uuid (M) === uuid
142
+ depmods[i] = M
143
+ end
144
+ else
145
+ modpath = find_package (string (modname))
146
+ modpath === nothing && return ErrorException (" Required dependency $modname not found in current path." )
147
+ mod = _require_search_from_serialized (modname, String (modpath))
148
+ if ! isa (mod, Bool)
149
+ for M in mod:: Vector{Any}
150
+ if module_name (M) === modname && module_uuid (M) === uuid
151
+ depmods[i] = M
152
+ break
153
+ end
154
+ end
155
+ for callback in package_callbacks
156
+ invokelatest (callback, modname)
157
+ end
158
+ end
159
+ end
160
+ isassigned (depmods, i) || return ErrorException (" Required dependency $modname failed to load from a cache file." )
161
+ end
162
+ # now load the path_to_try.ji file
163
+ restored = _include_from_serialized (path_to_try, depmods)
132
164
if ! isa (restored, Exception)
133
165
for M in restored:: Vector{Any}
166
+ M = M:: Module
134
167
if isdefined (M, Base. Docs. META)
135
168
push! (Base. Docs. modules, M)
136
169
end
170
+ if module_parent (M) === M
171
+ register_root_module (module_name (M), M)
172
+ end
137
173
end
138
174
end
139
175
return restored
@@ -145,12 +181,13 @@ end
145
181
function _require_search_from_serialized (mod:: Symbol , sourcepath:: String )
146
182
paths = find_all_in_cache_path (mod)
147
183
for path_to_try in paths:: Vector{String}
148
- if stale_cachefile (sourcepath, path_to_try)
184
+ deps = stale_cachefile (sourcepath, path_to_try)
185
+ if deps === true
149
186
continue
150
187
end
151
- restored = _require_from_serialized (mod, path_to_try)
188
+ restored = _require_from_serialized (mod, path_to_try, deps )
152
189
if isa (restored, Exception)
153
- if isa (restored, ErrorException) && endswith (restored . msg, " uuid did not match cache file. " )
190
+ if isa (restored, ErrorException)
154
191
# can't use this cache due to a module uuid mismatch,
155
192
# defer reporting error until after trying all of the possible matches
156
193
DEBUG_LOADING[] && info (" JL_DEBUG_LOADING: Failed to load $path_to_try because $(restored. msg) " )
@@ -183,7 +220,7 @@ const package_callbacks = Any[]
183
220
const include_callbacks = Any[]
184
221
185
222
# used to optionally track dependencies when requiring a module:
186
- const _concrete_dependencies = Any [] # these dependency versions are "set in stone", and the process should try to avoid invalidating them
223
+ const _concrete_dependencies = Pair{Symbol, UInt64} [] # these dependency versions are "set in stone", and the process should try to avoid invalidating them
187
224
const _require_dependencies = Any[] # a list of (mod, path, mtime) tuples that are the file dependencies of the module currently being precompiled
188
225
const _track_dependencies = Ref (false ) # set this to true to track the list of file dependencies
189
226
function _include_dependency (modstring:: AbstractString , _path:: AbstractString )
@@ -363,14 +400,6 @@ function unreference_module(key)
363
400
end
364
401
end
365
402
366
- function register_all (a)
367
- for m in a
368
- if module_parent (m) === m
369
- register_root_module (module_name (m), m)
370
- end
371
- end
372
- end
373
-
374
403
function _require (mod:: Symbol )
375
404
# dependency-tracking is only used for one top-level include(path),
376
405
# and is not applied recursively to imported modules:
@@ -396,13 +425,13 @@ function _require(mod::Symbol)
396
425
if path === nothing
397
426
throw (ArgumentError (" Module $name not found in current path.\n Run `Pkg.add(\" $name \" )` to install the $name package." ))
398
427
end
428
+ path = String (path)
399
429
400
430
# attempt to load the module file via the precompile cache locations
401
431
doneprecompile = false
402
432
if JLOptions (). use_compiled_modules != 0
403
433
doneprecompile = _require_search_from_serialized (mod, path)
404
434
if ! isa (doneprecompile, Bool)
405
- register_all (doneprecompile)
406
435
return
407
436
end
408
437
end
@@ -430,7 +459,6 @@ function _require(mod::Symbol)
430
459
warn (m, prefix= " WARNING: " )
431
460
# fall-through, TODO : disable __precompile__(true) error so that the normal include will succeed
432
461
else
433
- register_all (m)
434
462
return
435
463
end
436
464
end
@@ -452,7 +480,6 @@ function _require(mod::Symbol)
452
480
# TODO : disable __precompile__(true) error and do normal include instead of error
453
481
error (" Module $mod declares __precompile__(true) but require failed to create a usable precompiled cache file." )
454
482
end
455
- register_all (m)
456
483
end
457
484
finally
458
485
toplevel_load[] = last
@@ -545,7 +572,7 @@ function evalfile(path::AbstractString, args::Vector{String}=String[])
545
572
end
546
573
evalfile (path:: AbstractString , args:: Vector ) = evalfile (path, String[args... ])
547
574
548
- function create_expr_cache (input:: String , output:: String , concrete_deps:: Vector{Any} )
575
+ function create_expr_cache (input:: String , output:: String , concrete_deps:: typeof (_concrete_dependencies) )
549
576
rm (output, force= true ) # Remove file if it exists
550
577
code_object = """
551
578
while !eof(STDIN)
@@ -612,12 +639,12 @@ function compilecache(name::String)
612
639
if ! isdir (cachepath)
613
640
mkpath (cachepath)
614
641
end
615
- cachefile:: String = abspath (cachepath, name * " .ji" )
642
+ cachefile:: String = abspath (cachepath, " $name .ji" )
616
643
# build up the list of modules that we want the precompile process to preserve
617
644
concrete_deps = copy (_concrete_dependencies)
618
- for (key,mod) in loaded_modules
645
+ for (key, mod) in loaded_modules
619
646
if ! (mod === Main || mod === Core || mod === Base)
620
- push! (concrete_deps, ( key, module_uuid (mod) ))
647
+ push! (concrete_deps, key => module_uuid (mod))
621
648
end
622
649
end
623
650
# run the expression and cache the result
@@ -644,13 +671,13 @@ module_uuid(m::Module) = ccall(:jl_module_uuid, UInt64, (Any,), m)
644
671
isvalid_cache_header (f:: IOStream ) = 0 != ccall (:jl_read_verify_header , Cint, (Ptr{Void},), f. ios)
645
672
646
673
function parse_cache_header (f:: IO )
647
- modules = Dict { Symbol,UInt64} ()
674
+ modules = Vector {Pair{ Symbol, UInt64} } ()
648
675
while true
649
676
n = ntoh (read (f, Int32))
650
677
n == 0 && break
651
678
sym = Symbol (read (f, n)) # module symbol
652
679
uuid = ntoh (read (f, UInt64)) # module UUID (mostly just a timestamp)
653
- modules[ sym] = uuid
680
+ push! ( modules, sym => uuid)
654
681
end
655
682
totbytes = ntoh (read (f, Int64)) # total bytes for file dependencies
656
683
# read the list of files
@@ -669,13 +696,13 @@ function parse_cache_header(f::IO)
669
696
@assert totbytes == 12 " header of cache file appears to be corrupt"
670
697
srctextpos = ntoh (read (f, Int64))
671
698
# read the list of modules that are required to be present during loading
672
- required_modules = Dict { Symbol,UInt64} ()
699
+ required_modules = Vector {Pair{ Symbol, UInt64} } ()
673
700
while true
674
701
n = ntoh (read (f, Int32))
675
702
n == 0 && break
676
703
sym = Symbol (read (f, n)) # module symbol
677
704
uuid = ntoh (read (f, UInt64)) # module UUID
678
- required_modules[ sym] = uuid
705
+ push! ( required_modules, sym => uuid)
679
706
end
680
707
return modules, files, required_modules, srctextpos
681
708
end
@@ -736,6 +763,8 @@ function read_dependency_src(cachefile::String, filename::AbstractString)
736
763
end
737
764
end
738
765
766
+ # returns true if it "cachefile.ji" is stale relative to "modpath.jl"
767
+ # otherwise returns the list of dependencies to also check
739
768
function stale_cachefile (modpath:: String , cachefile:: String )
740
769
io = open (cachefile, " r" )
741
770
try
@@ -744,13 +773,12 @@ function stale_cachefile(modpath::String, cachefile::String)
744
773
return true # invalid cache file
745
774
end
746
775
modules, files, required_modules = parse_cache_header (io)
776
+ modules = Dict {Symbol, UInt64} (modules)
747
777
748
778
# Check if transitive dependencies can be fullfilled
749
- for mod in keys (required_modules)
750
- if mod == :Main || mod == :Core || mod == :Base
751
- continue
779
+ for (mod, uuid_req) in required_modules
752
780
# Module is already loaded
753
- elseif root_module_exists (mod)
781
+ if root_module_exists (mod)
754
782
continue
755
783
end
756
784
name = string (mod)
@@ -768,7 +796,7 @@ function stale_cachefile(modpath::String, cachefile::String)
768
796
uuid = get (modules, mod, UInt64 (0 ))
769
797
if uuid != = UInt64 (0 )
770
798
if uuid === uuid_req
771
- return false # this is the file we want
799
+ return required_modules # this is the file we want
772
800
end
773
801
DEBUG_LOADING[] && info (" JL_DEBUG_LOADING: Rejecting cache file $cachefile because it provides the wrong uuid (got $uuid ) for $mod (want $uuid_req )." )
774
802
return true # cachefile doesn't provide the required version of the dependency
@@ -797,7 +825,7 @@ function stale_cachefile(modpath::String, cachefile::String)
797
825
return true
798
826
end
799
827
800
- return false # fresh cachefile
828
+ return required_modules # fresh cachefile
801
829
finally
802
830
close (io)
803
831
end
0 commit comments