Skip to content

Commit ecaff03

Browse files
committed
automatic recompilation of stale cache files (fixes JuliaLang#12259)
1 parent 8fc54ac commit ecaff03

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

base/loading.jl

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ function _include_from_serialized(content::Vector{UInt8})
5858
end
5959

6060
# returns an array of modules loaded, or nothing if failed
61-
function _require_from_serialized(node::Int, path_to_try::ByteString, toplevel_load::Bool)
61+
function _require_from_serialized(node::Int, mod::Symbol, path_to_try::ByteString, toplevel_load::Bool)
6262
restored = nothing
6363
if toplevel_load && myid() == 1 && nprocs() > 1
64+
recompile_stale(mod, path_to_try)
6465
# broadcast top-level import/using from node 1 (only)
6566
if node == myid()
6667
content = open(readbytes, path_to_try)
@@ -78,6 +79,7 @@ function _require_from_serialized(node::Int, path_to_try::ByteString, toplevel_l
7879
end
7980
end
8081
elseif node == myid()
82+
myid() == 1 && recompile_stale(mod, path_to_try)
8183
restored = ccall(:jl_restore_incremental, Any, (Ptr{Uint8},), path_to_try)
8284
else
8385
content = remotecall_fetch(node, open, readbytes, path_to_try)
@@ -89,8 +91,9 @@ end
8991

9092
function _require_from_serialized(node::Int, mod::Symbol, toplevel_load::Bool)
9193
paths = @fetchfrom node find_all_in_cache_path(mod)
94+
sort!(paths, by=mtime, rev=true) # try newest cachefiles first
9295
for path_to_try in paths
93-
restored = _require_from_serialized(node, path_to_try, toplevel_load)
96+
restored = _require_from_serialized(node, mod, path_to_try, toplevel_load)
9497
if restored === nothing
9598
warn("deserialization checks failed while attempting to load cache from $path_to_try")
9699
else
@@ -152,7 +155,7 @@ function require(mod::Symbol)
152155
if JLOptions().incremental != 0
153156
# spawn off a new incremental compile task from node 1 for recursive `require` calls
154157
cachefile = compile(mod)
155-
if nothing === _require_from_serialized(1, cachefile, last)
158+
if nothing === _require_from_serialized(1, mod, cachefile, last)
156159
warn("require failed to create a precompiled cache file")
157160
end
158161
return
@@ -315,3 +318,30 @@ function cache_dependencies(cachefile::AbstractString)
315318
end
316319
return modules, files
317320
end
321+
322+
function stale_cachefile(cachefile::AbstractString, cachefile_mtime::Real=mtime(cachefile))
323+
modules, files = cache_dependencies(cachefile)
324+
for f in files
325+
if mtime(f) > cachefile_mtime
326+
return true
327+
end
328+
end
329+
# files are not stale, so module list is valid and needs checking
330+
for (M,uuid) in modules
331+
if !isdefined(Main, M)
332+
require(M) # should recursively recompile module M if stale
333+
end
334+
if module_uuid(Main.(M)) != uuid
335+
return true
336+
end
337+
end
338+
return false # fresh cachefile
339+
end
340+
341+
function recompile_stale(mod, cachefile)
342+
cachestat = stat(cachefile)
343+
if iswritable(cachestat) && stale_cachefile(cachefile, cachestat.mtime)
344+
info("Recompiling stale cache file $cachefile for module $mod.")
345+
create_expr_cache(find_in_path(string(mod)), cachefile)
346+
end
347+
end

0 commit comments

Comments
 (0)