Skip to content

Commit 5730079

Browse files
committed
Short-cut parsing the compiler if you dev the loaded version
This adds a special mechanism to shortcut parsing/loading the whole compiler if the version you have dev'ed happens to exactly match (under the usual criteria for cache validation) match the version that you have compiled into the system image. As written, this does not extend to `add`'ed packages. I would like to make that work in the future, but the refactoring required is too extensive for my current taste and somewhat independent. Fortuantely, it's just an optimization, so it can be added later. Still, I would like to keep this path for `dev` so that we can exercise it to see if there's any other problems with it. Demo: With `dev stdlib/Compiler`, we get a small `7k` .so file, since the Compiler does not get re-loaded. ``` julia> @time using Compiler ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since pkgimage /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so was not found └ @ Base loading.jl:3945 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_ajVhJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since the flags are mismatched │ requested flags: use_pkgimages = true, debug_level = 1, check_bounds = 0, inline = true, opt_level = 2 [163] │ cache file: use_pkgimages = true, debug_level = 2, check_bounds = 0, inline = true, opt_level = 2 [165] └ @ Base loading.jl:3918 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since pkgimage /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so was not found └ @ Base loading.jl:3945 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_ajVhJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since the flags are mismatched │ requested flags: use_pkgimages = true, debug_level = 1, check_bounds = 0, inline = true, opt_level = 2 [163] │ cache file: use_pkgimages = true, debug_level = 2, check_bounds = 0, inline = true, opt_level = 2 [165] └ @ Base loading.jl:3918 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since pkgimage /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so was not found └ @ Base loading.jl:3945 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_ajVhJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since the flags are mismatched │ requested flags: use_pkgimages = true, debug_level = 1, check_bounds = 0, inline = true, opt_level = 2 [163] │ cache file: use_pkgimages = true, debug_level = 2, check_bounds = 0, inline = true, opt_level = 2 [165] └ @ Base loading.jl:3918 [ Info: Precompiling Compiler [807dbc54-b67e-4c79-8afb-eafe4df6f2e1] (cache misses: mismatched flags (2), missing ocachefile (2)) ┌ Debug: Generating object cache file for Compiler [807dbc54-b67e-4c79-8afb-eafe4df6f2e1] └ @ Base loading.jl:3021 ┌ Debug: Loading object cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so for Compiler [807dbc54-b67e-4c79-8afb-eafe4df6f2e1] └ @ Base loading.jl:1277 1.000245 seconds (507.60 k allocations: 29.245 MiB, 1.68% gc time, 65.46% compilation time) shell> ls -la /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so -rwxrwxr-x 1 keno keno 7112 Nov 1 07:33 /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so julia> Compiler === Base.Compiler true ``` Next, we dev the Compiler from another Julia version. Now it just treats is as a regular package load and generates a 5MB .ji that contains the usual pkgimage. ``` (@v1.12) pkg> dev /home/keno/julia2/stdlib/Compiler Resolving package versions... Updating `~/.julia/environments/v1.12/Project.toml` [807dbc54] + Compiler v0.0.1 `~/julia2/stdlib/Compiler` Updating `~/.julia/environments/v1.12/Manifest.toml` [807dbc54] + Compiler v0.0.1 `~/julia2/stdlib/Compiler` julia> using Compiler ┌ Debug: Rejecting stale cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.ji because file size of /home/keno/julia2/stdlib/Compiler/src/Compiler.jl has changed (file size 5958, before 5949) └ @ Base loading.jl:3875 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_ajVhJ.ji for Base.PkgId(Base.UUID("807dbc54-b67e-4c79-8afb-eafe4df6f2e1"), "Compiler") since the flags are mismatched │ requested flags: use_pkgimages = true, debug_level = 1, check_bounds = 0, inline = true, opt_level = 2 [163] │ cache file: use_pkgimages = true, debug_level = 2, check_bounds = 0, inline = true, opt_level = 2 [165] └ @ Base loading.jl:3918 ┌ Debug: Rejecting stale cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.ji because file size of /home/keno/julia2/stdlib/Compiler/src/Compiler.jl has changed (file size 5958, before 5949) └ @ Base loading.jl:3875 ┌ Debug: Rejecting cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_ajVhJ.ji for Base.PkgId(nothing, "") since the flags are mismatched │ requested flags: use_pkgimages = true, debug_level = 1, check_bounds = 0, inline = true, opt_level = 2 [163] │ cache file: use_pkgimages = true, debug_level = 2, check_bounds = 0, inline = true, opt_level = 2 [165] └ @ Base loading.jl:3918 Precompiling Compiler finished. 1 dependency successfully precompiled in 3 seconds ┌ Debug: Loading object cache file /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so for Compiler [807dbc54-b67e-4c79-8afb-eafe4df6f2e1] └ @ Base loading.jl:1277 shell> ls -la /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so -rwxrwxr-x 1 keno keno 5706792 Nov 1 07:40 /home/keno/.julia/compiled/v1.12/Compiler/DqelA_OpSbJ.so julia> Compiler === Base.Compiler false ```
1 parent b2f4366 commit 5730079

File tree

8 files changed

+183
-83
lines changed

8 files changed

+183
-83
lines changed

base/Base.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,18 @@ end
472472
# enable threads support
473473
@eval PCRE PCRE_COMPILE_LOCK = Threads.SpinLock()
474474

475+
# Record dependency information for files beloning to the Compiler, so that
476+
# we know whether the .ji can just give the Base copy or not.
477+
# TODO: We may want to do this earlier to avoid TOCTOU issues.
478+
const _compiler_require_dependencies = Any[]
479+
for i = 1:length(_included_files)
480+
isassigned(_included_files, i) || continue
481+
(mod, file) = _included_files[i]
482+
if parentmodule(mod) === Compiler || endswith(file, "/Compiler.jl")
483+
_include_dependency!(_compiler_require_dependencies, true, mod, file, true, false)
484+
end
485+
end
486+
475487
end
476488

477489
# Ensure this file is also tracked

base/loading.jl

Lines changed: 99 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,15 +2239,22 @@ const include_callbacks = Any[]
22392239
const _concrete_dependencies = Pair{PkgId,UInt128}[] # these dependency versions are "set in stone", because they are explicitly loaded, and the process should try to avoid invalidating them
22402240
const _require_dependencies = Any[] # a list of (mod, abspath, fsize, hash, mtime) tuples that are the file dependencies of the module currently being precompiled
22412241
const _track_dependencies = Ref(false) # set this to true to track the list of file dependencies
2242-
function _include_dependency(mod::Module, _path::AbstractString; track_content=true,
2243-
path_may_be_dir=false)
2242+
2243+
function _include_dependency(mod::Module, _path::AbstractString; track_content::Bool=true,
2244+
path_may_be_dir::Bool=false)
2245+
_include_dependency!(_require_dependencies, _track_dependencies[], mod, _path, track_content, path_may_be_dir)
2246+
end
2247+
2248+
function _include_dependency!(dep_list::Vector{Any}, track_dependencies::Bool,
2249+
mod::Module, _path::AbstractString,
2250+
track_content::Bool, path_may_be_dir::Bool)
22442251
prev = source_path(nothing)
22452252
if prev === nothing
22462253
path = abspath(_path)
22472254
else
22482255
path = normpath(joinpath(dirname(prev), _path))
22492256
end
2250-
if !_track_dependencies[]
2257+
if !track_dependencies[]
22512258
if !path_may_be_dir && !isfile(path)
22522259
throw(SystemError("opening file $(repr(path))", Libc.ENOENT))
22532260
elseif path_may_be_dir && !Filesystem.isreadable(path)
@@ -2258,9 +2265,9 @@ function _include_dependency(mod::Module, _path::AbstractString; track_content=t
22582265
if track_content
22592266
hash = isdir(path) ? _crc32c(join(readdir(path))) : open(_crc32c, path, "r")
22602267
# use mtime=-1.0 here so that fsize==0 && mtime==0.0 corresponds to a missing include_dependency
2261-
push!(_require_dependencies, (mod, path, filesize(path), hash, -1.0))
2268+
push!(dep_list, (mod, path, filesize(path), hash, -1.0))
22622269
else
2263-
push!(_require_dependencies, (mod, path, UInt64(0), UInt32(0), mtime(path)))
2270+
push!(dep_list, (mod, path, UInt64(0), UInt32(0), mtime(path)))
22642271
end
22652272
end
22662273
end
@@ -2555,7 +2562,21 @@ end
25552562
root_module_exists(key::PkgId) = @lock require_lock haskey(loaded_modules, key)
25562563
maybe_root_module(key::PkgId) = @lock require_lock get(loaded_modules, key, nothing)
25572564

2558-
loaded_modules_array() = @lock require_lock copy(loaded_modules_order)
2565+
function loaded_modules_array()
2566+
@lock require_lock begin
2567+
ret = copy(loaded_modules_order)
2568+
if generating_output(false)
2569+
# If we're generating a non-incremental system image, also add the
2570+
# Compiler to the module list so that we generate native code for it.
2571+
# However, we do not add it to `loaded_modules_order` unless there
2572+
# is a Julia-level dependency on it. The (non-)loadedness of the compiler
2573+
# is an implementation detail and we do not want ordinary pkgimages to
2574+
# acquire a dependency on the Compiler if they do not use it internally.
2575+
push!(ret, Compiler)
2576+
end
2577+
return ret
2578+
end
2579+
end
25592580

25602581
# after unreference_module, a subsequent require call will try to load a new copy of it, if stale
25612582
# reload(m) = (unreference_module(m); require(m))
@@ -3326,6 +3347,10 @@ mutable struct CacheHeaderIncludes
33263347
const modpath::Vector{String} # seemingly not needed in Base, but used by Revise
33273348
end
33283349

3350+
function CacheHeaderIncludes(dep_tuple::Tuple{Module, String, Int64, UInt32, Float64})
3351+
return CacheHeaderIncludes(PkgId(dep_tuple[1]), dep_tuple[2:end]..., String[])
3352+
end
3353+
33293354
function replace_depot_path(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation())
33303355
for depot in depots
33313356
if startswith(path, string(depot, Filesystem.pathsep())) || path == depot
@@ -3865,6 +3890,56 @@ function list_reasons(reasons::Dict{String,Int})
38653890
end
38663891
list_reasons(::Nothing) = ""
38673892

3893+
function any_includes_stale(includes::Vector{CacheHeaderIncludes}, cachefile::String, reasons::Union{Dict{String,Int},Nothing}=nothing)
3894+
for chi in includes
3895+
f, fsize_req, hash_req, ftime_req = chi.filename, chi.fsize, chi.hash, chi.mtime
3896+
if startswith(f, string("@depot", Filesystem.pathsep()))
3897+
@debug("Rejecting stale cache file $cachefile because its depot could not be resolved")
3898+
record_reason(reasons, "nonresolveable depot")
3899+
return true
3900+
end
3901+
if !ispath(f)
3902+
_f = fixup_stdlib_path(f)
3903+
if _f != f && isfile(_f) && startswith(_f, Sys.STDLIB)
3904+
continue
3905+
end
3906+
@debug "Rejecting stale cache file $cachefile because file $f does not exist"
3907+
record_reason(reasons, "missing sourcefile")
3908+
return true
3909+
end
3910+
if ftime_req >= 0.0
3911+
# this is an include_dependency for which we only recorded the mtime
3912+
ftime = mtime(f)
3913+
is_stale = ( ftime != ftime_req ) &&
3914+
( ftime != floor(ftime_req) ) && # Issue #13606, PR #13613: compensate for Docker images rounding mtimes
3915+
( ftime != ceil(ftime_req) ) && # PR: #47433 Compensate for CirceCI's truncating of timestamps in its caching
3916+
( ftime != trunc(ftime_req, digits=6) ) && # Issue #20837, PR #20840: compensate for GlusterFS truncating mtimes to microseconds
3917+
( ftime != 1.0 ) && # PR #43090: provide compatibility with Nix mtime.
3918+
!( 0 < (ftime_req - ftime) < 1e-6 ) # PR #45552: Compensate for Windows tar giving mtimes that may be incorrect by up to one microsecond
3919+
if is_stale
3920+
@debug "Rejecting stale cache file $cachefile because mtime of include_dependency $f has changed (mtime $ftime, before $ftime_req)"
3921+
record_reason(reasons, "include_dependency mtime change")
3922+
return true
3923+
end
3924+
else
3925+
fstat = stat(f)
3926+
fsize = filesize(fstat)
3927+
if fsize != fsize_req
3928+
@debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)"
3929+
record_reason(reasons, "include_dependency fsize change")
3930+
return true
3931+
end
3932+
hash = isdir(fstat) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r")
3933+
if hash != hash_req
3934+
@debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)"
3935+
record_reason(reasons, "include_dependency fhash change")
3936+
return true
3937+
end
3938+
end
3939+
end
3940+
return false
3941+
end
3942+
38683943
# returns true if it "cachefile.ji" is stale relative to "modpath.jl" and build_id for modkey
38693944
# otherwise returns the list of dependencies to also check
38703945
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false, requested_flags::CacheFlags=CacheFlags(), reasons=nothing)
@@ -4024,51 +4099,8 @@ end
40244099
return true
40254100
end
40264101
end
4027-
for chi in includes
4028-
f, fsize_req, hash_req, ftime_req = chi.filename, chi.fsize, chi.hash, chi.mtime
4029-
if startswith(f, string("@depot", Filesystem.pathsep()))
4030-
@debug("Rejecting stale cache file $cachefile because its depot could not be resolved")
4031-
record_reason(reasons, "nonresolveable depot")
4032-
return true
4033-
end
4034-
if !ispath(f)
4035-
_f = fixup_stdlib_path(f)
4036-
if _f != f && isfile(_f) && startswith(_f, Sys.STDLIB)
4037-
continue
4038-
end
4039-
@debug "Rejecting stale cache file $cachefile because file $f does not exist"
4040-
record_reason(reasons, "missing sourcefile")
4041-
return true
4042-
end
4043-
if ftime_req >= 0.0
4044-
# this is an include_dependency for which we only recorded the mtime
4045-
ftime = mtime(f)
4046-
is_stale = ( ftime != ftime_req ) &&
4047-
( ftime != floor(ftime_req) ) && # Issue #13606, PR #13613: compensate for Docker images rounding mtimes
4048-
( ftime != ceil(ftime_req) ) && # PR: #47433 Compensate for CirceCI's truncating of timestamps in its caching
4049-
( ftime != trunc(ftime_req, digits=6) ) && # Issue #20837, PR #20840: compensate for GlusterFS truncating mtimes to microseconds
4050-
( ftime != 1.0 ) && # PR #43090: provide compatibility with Nix mtime.
4051-
!( 0 < (ftime_req - ftime) < 1e-6 ) # PR #45552: Compensate for Windows tar giving mtimes that may be incorrect by up to one microsecond
4052-
if is_stale
4053-
@debug "Rejecting stale cache file $cachefile because mtime of include_dependency $f has changed (mtime $ftime, before $ftime_req)"
4054-
record_reason(reasons, "include_dependency mtime change")
4055-
return true
4056-
end
4057-
else
4058-
fstat = stat(f)
4059-
fsize = filesize(fstat)
4060-
if fsize != fsize_req
4061-
@debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)"
4062-
record_reason(reasons, "include_dependency fsize change")
4063-
return true
4064-
end
4065-
hash = isdir(fstat) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r")
4066-
if hash != hash_req
4067-
@debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)"
4068-
record_reason(reasons, "include_dependency fhash change")
4069-
return true
4070-
end
4071-
end
4102+
if any_includes_stale(includes, cachefile, reasons)
4103+
return true
40724104
end
40734105
end
40744106

@@ -4189,5 +4221,21 @@ end
41894221

41904222
precompile(include_package_for_output, (PkgId, String, Vector{String}, Vector{String}, Vector{String}, typeof(_concrete_dependencies), Nothing)) || @assert false
41914223
precompile(include_package_for_output, (PkgId, String, Vector{String}, Vector{String}, Vector{String}, typeof(_concrete_dependencies), String)) || @assert false
4224+
<<<<<<< HEAD
41924225
precompile(create_expr_cache, (PkgId, String, String, String, typeof(_concrete_dependencies), Cmd, CacheFlags, IO, IO)) || @assert false
41934226
precompile(create_expr_cache, (PkgId, String, String, Nothing, typeof(_concrete_dependencies), Cmd, CacheFlags, IO, IO)) || @assert false
4227+
=======
4228+
precompile(create_expr_cache, (PkgId, String, String, String, typeof(_concrete_dependencies), Cmd, IO, IO)) || @assert false
4229+
precompile(create_expr_cache, (PkgId, String, String, Nothing, typeof(_concrete_dependencies), Cmd, IO, IO)) || @assert false
4230+
4231+
is_core_or_base(mod::Module) = mod === Core || mod === Base
4232+
function prepare_compiler_stub_image!()
4233+
ccall(:jl_add_to_module_init_list, Cvoid, (Any,), Compiler)
4234+
# Drop any dependencies on loaded modules. We know Base.Compiler only depends
4235+
# on very basic `Base` functionality, so we don't want to pick up dependencies
4236+
# on other stdlibs that may be loaded.
4237+
filter!(p->is_core_or_base(p.second), loaded_modules)
4238+
register_root_module(Compiler)
4239+
filter!(is_core_or_base, loaded_modules_order)
4240+
end
4241+
>>>>>>> 84d9bc1466 (Short-cut parsing the compiler if you dev the loaded version)

contrib/generate_precompile.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe
359359
eval(PrecompileStagingArea, :(const $(Symbol(_mod)) = $_mod))
360360
end
361361
end
362+
eval(PrecompileStagingArea, :(const Compiler = Base.Compiler))
362363

363364
n_succeeded = 0
364365
# Make statements unique

src/module.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ JL_DLLEXPORT jl_uuid_t jl_module_uuid(jl_module_t* m) { return m->uuid; }
12761276

12771277
// TODO: make this part of the module constructor and read-only?
12781278
JL_DLLEXPORT void jl_set_module_uuid(jl_module_t *m, jl_uuid_t uuid) { m->uuid = uuid; }
1279+
JL_DLLEXPORT void jl_set_module_parent(jl_module_t *m, jl_module_t *parent) { m->parent = parent; }
12791280

12801281
int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT
12811282
{
@@ -1308,15 +1309,20 @@ JL_DLLEXPORT void jl_clear_implicit_imports(jl_module_t *m)
13081309
JL_UNLOCK(&m->lock);
13091310
}
13101311

1312+
JL_DLLEXPORT void jl_add_to_module_init_list(jl_value_t *mod)
1313+
{
1314+
if (jl_module_init_order == NULL)
1315+
jl_module_init_order = jl_alloc_vec_any(0);
1316+
jl_array_ptr_1d_push(jl_module_init_order, mod);
1317+
}
1318+
13111319
JL_DLLEXPORT void jl_init_restored_module(jl_value_t *mod)
13121320
{
13131321
if (!jl_generating_output() || jl_options.incremental) {
13141322
jl_module_run_initializer((jl_module_t*)mod);
13151323
}
13161324
else {
1317-
if (jl_module_init_order == NULL)
1318-
jl_module_init_order = jl_alloc_vec_any(0);
1319-
jl_array_ptr_1d_push(jl_module_init_order, mod);
1325+
jl_add_to_module_init_list(mod);
13201326
}
13211327
}
13221328

src/precompile_utils.c

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@ static void *jl_precompile(int all)
281281
return native_code;
282282
}
283283

284+
static int suppress_precompile = 0;
285+
JL_DLLEXPORT void jl_suppress_precompile(int suppress)
286+
{
287+
suppress_precompile = suppress;
288+
}
289+
284290
static void *jl_precompile_worklist(jl_array_t *worklist, jl_array_t *extext_methods, jl_array_t *new_ext_cis)
285291
{
286292
if (!worklist)
@@ -289,34 +295,36 @@ static void *jl_precompile_worklist(jl_array_t *worklist, jl_array_t *extext_met
289295
// type signatures that were inferred but haven't been compiled
290296
jl_array_t *m = jl_alloc_vec_any(0);
291297
JL_GC_PUSH1(&m);
292-
size_t i, n = jl_array_nrows(worklist);
293-
for (i = 0; i < n; i++) {
294-
jl_module_t *mod = (jl_module_t*)jl_array_ptr_ref(worklist, i);
295-
assert(jl_is_module(mod));
296-
foreach_mtable_in_module(mod, precompile_enq_all_specializations_, m);
297-
}
298-
n = jl_array_nrows(extext_methods);
299-
for (i = 0; i < n; i++) {
300-
jl_method_t *method = (jl_method_t*)jl_array_ptr_ref(extext_methods, i);
301-
assert(jl_is_method(method));
302-
jl_value_t *specializations = jl_atomic_load_relaxed(&method->specializations);
303-
if (!jl_is_svec(specializations)) {
304-
precompile_enq_specialization_((jl_method_instance_t*)specializations, m);
298+
if (!suppress_precompile) {
299+
size_t i, n = jl_array_nrows(worklist);
300+
for (i = 0; i < n; i++) {
301+
jl_module_t *mod = (jl_module_t*)jl_array_ptr_ref(worklist, i);
302+
assert(jl_is_module(mod));
303+
foreach_mtable_in_module(mod, precompile_enq_all_specializations_, m);
305304
}
306-
else {
307-
size_t j, l = jl_svec_len(specializations);
308-
for (j = 0; j < l; j++) {
309-
jl_value_t *mi = jl_svecref(specializations, j);
310-
if (mi != jl_nothing)
311-
precompile_enq_specialization_((jl_method_instance_t*)mi, m);
305+
n = jl_array_nrows(extext_methods);
306+
for (i = 0; i < n; i++) {
307+
jl_method_t *method = (jl_method_t*)jl_array_ptr_ref(extext_methods, i);
308+
assert(jl_is_method(method));
309+
jl_value_t *specializations = jl_atomic_load_relaxed(&method->specializations);
310+
if (!jl_is_svec(specializations)) {
311+
precompile_enq_specialization_((jl_method_instance_t*)specializations, m);
312+
}
313+
else {
314+
size_t j, l = jl_svec_len(specializations);
315+
for (j = 0; j < l; j++) {
316+
jl_value_t *mi = jl_svecref(specializations, j);
317+
if (mi != jl_nothing)
318+
precompile_enq_specialization_((jl_method_instance_t*)mi, m);
319+
}
312320
}
313321
}
314-
}
315-
if (new_ext_cis) {
316-
n = jl_array_nrows(new_ext_cis);
317-
for (i = 0; i < n; i++) {
318-
jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(new_ext_cis, i);
319-
precompile_enq_specialization_(ci->def, m);
322+
if (new_ext_cis) {
323+
n = jl_array_nrows(new_ext_cis);
324+
for (i = 0; i < n; i++) {
325+
jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(new_ext_cis, i);
326+
precompile_enq_specialization_(ci->def, m);
327+
}
320328
}
321329
}
322330
void *native_code = jl_precompile_(m, 1);

stdlib/Compiler/src/Compiler.jl

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3+
# When generating an incremental precompile file, we first check whether we
4+
# already have a copy of this *exact* code in the system image. If so, we
5+
# simply generates a pkgimage that has the dependency edges we recorded in
6+
# the system image and simply returns that copy of the compiler. If not,
7+
# we proceed to load/precompile this as an ordinary package.
8+
if isdefined(Base, :generating_output) && Base.generating_output(true) &&
9+
Base.samefile(Base._compiler_require_dependencies[1][2], @eval @__FILE__) &&
10+
!Base.any_includes_stale(
11+
map(Base.CacheHeaderIncludes, Base._compiler_require_dependencies),
12+
"sysimg", nothing)
13+
14+
Base.prepare_compiler_stub_image!()
15+
append!(Base._require_dependencies, Base._compiler_require_dependencies)
16+
# There isn't much point in precompiling native code - downstream users will
17+
# specialize their own versions of the compiler code and we don't activate
18+
# the compiler by default anyway, so let's save ourselves some disk space.
19+
ccall(:jl_suppress_precompile, Cvoid, (Cint,), 1)
320

4-
baremodule Compiler
21+
else
22+
23+
@eval baremodule Compiler
24+
25+
# Needs to match UUID defined in Project.toml
26+
ccall(:jl_set_module_uuid, Cvoid, (Any, NTuple{2, UInt64}), Compiler,
27+
(0x807dbc54_b67e_4c79, 0x8afb_eafe4df6f2e1))
28+
ccall(:jl_set_module_parent, Cvoid, (Any, Any), Compiler, Compiler)
529

630
using Core.Intrinsics, Core.IR
731

@@ -136,3 +160,5 @@ include("optimize.jl")
136160
include("bootstrap.jl")
137161

138162
end
163+
164+
end

stdlib/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ $(foreach jll,$(JLLS),$(eval $(call download-artifacts-toml,$(jll))))
4343
STDLIBS = Artifacts Base64 CRC32c Dates FileWatching \
4444
Future InteractiveUtils Libdl LibGit2 LinearAlgebra Logging \
4545
Markdown Mmap Printf Profile Random REPL Serialization \
46-
SharedArrays Sockets Test TOML Unicode UUIDs Compiler \
46+
SharedArrays Sockets Test TOML Unicode UUIDs \
4747
$(JLL_NAMES)
4848

4949
STDLIBS_EXT = Pkg Statistics LazyArtifacts LibCURL DelimitedFiles Downloads ArgTools \
@@ -56,7 +56,6 @@ ifneq ($(filter $(STDLIBS),$(STDLIBS_EXT)),)
5656
$(error ERROR duplicated STDLIBS in list)
5757
endif
5858

59-
6059
# Generate symlinks to all stdlibs at usr/share/julia/stdlib/vX.Y/
6160
$(foreach module, $(STDLIBS), $(eval $(call symlink_target,$$(JULIAHOME)/stdlib/$(module),$$(build_datarootdir)/julia/stdlib/$$(VERSDIR),$(module))))
6261

0 commit comments

Comments
 (0)