Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into sds/tkf/type-capturing
Browse files Browse the repository at this point in the history
  • Loading branch information
simeonschaub committed Oct 4, 2024
2 parents fbe59cc + 1c5cd96 commit e6eef3c
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 102 deletions.
2 changes: 1 addition & 1 deletion base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ function __init__()
empty!(explicit_loaded_modules)
empty!(loaded_precompiles) # If we load a packageimage when building the image this might not be empty
for (mod, key) in module_keys
loaded_precompiles[key => module_build_id(mod)] = mod
push!(get!(Vector{Module}, loaded_precompiles, key), mod)
end
if haskey(ENV, "JULIA_MAX_NUM_PRECOMPILE_FILES")
MAX_NUM_PRECOMPILE_FILES[] = parse(Int, ENV["JULIA_MAX_NUM_PRECOMPILE_FILES"])
Expand Down
10 changes: 6 additions & 4 deletions base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -732,11 +732,13 @@ function compute_frameinfo(ir::IRCode)
inst = ir[SSAValue(idx)]
stmt = inst[:stmt]
if isa(stmt, EnterNode)
@assert idx nstmts "try/catch inside new_nodes unsupported"
tryregions === nothing && (tryregions = UnitRange{Int}[])
leave_block = stmt.catch_dest
leave_pc = first(ir.cfg.blocks[leave_block].stmts)
push!(tryregions, idx:leave_pc)
if leave_block 0
@assert idx nstmts "try/catch inside new_nodes unsupported"
tryregions === nothing && (tryregions = UnitRange{Int}[])
leave_pc = first(ir.cfg.blocks[leave_block].stmts)
push!(tryregions, idx:leave_pc)
end
elseif arrayinfo !== nothing
# TODO this super limited alias analysis is able to handle only very simple cases
# this should be replaced with a proper forward dimension analysis
Expand Down
2 changes: 1 addition & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ end

# Restrict inlining to hardware-supported arithmetic types, which
# are fast enough to benefit from inlining.
const HWReal = Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64}
const HWReal = Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float16,Float32,Float64}
const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}}

# Inline x^2 and x^3 for Val
Expand Down
184 changes: 103 additions & 81 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No
dep = depmods[i]
dep isa Module && continue
_, depkey, depbuild_id = dep::Tuple{String, PkgId, UInt128}
dep = loaded_precompiles[depkey => depbuild_id]
dep = something(maybe_loaded_precompile(depkey, depbuild_id))
@assert PkgId(dep) == depkey && module_build_id(dep) === depbuild_id
depmods[i] = dep
end
Expand Down Expand Up @@ -1337,6 +1337,7 @@ end

function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
# This function is also used by PkgCacheInspector.jl
assert_havelock(require_lock)
restored = sv[1]::Vector{Any}
for M in restored
M = M::Module
Expand All @@ -1345,7 +1346,7 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
end
if parentmodule(M) === M
push!(loaded_modules_order, M)
loaded_precompiles[pkg => module_build_id(M)] = M
push!(get!(Vector{Module}, loaded_precompiles, pkg), M)
end
end

Expand Down Expand Up @@ -1945,90 +1946,102 @@ end
assert_havelock(require_lock)
paths = find_all_in_cache_path(pkg, DEPOT_PATH)
newdeps = PkgId[]
for path_to_try in paths::Vector{String}
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try; reasons, stalecheck)
if staledeps === true
continue
end
try
staledeps, ocachefile, newbuild_id = staledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
# finish checking staledeps module graph
for i in eachindex(staledeps)
dep = staledeps[i]
dep isa Module && continue
modpath, modkey, modbuild_id = dep::Tuple{String, PkgId, UInt128}
modpaths = find_all_in_cache_path(modkey, DEPOT_PATH)
for modpath_to_try in modpaths
modstaledeps = stale_cachefile(modkey, modbuild_id, modpath, modpath_to_try; stalecheck)
if modstaledeps === true
continue
end
modstaledeps, modocachepath, _ = modstaledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
staledeps[i] = (modpath, modkey, modbuild_id, modpath_to_try, modstaledeps, modocachepath)
@goto check_next_dep
try_build_ids = UInt128[build_id]
if build_id == UInt128(0)
let loaded = get(loaded_precompiles, pkg, nothing)
if loaded !== nothing
for mod in loaded # try these in reverse original load order to see if one is already valid
pushfirst!(try_build_ids, module_build_id(mod))
end
@debug "Rejecting cache file $path_to_try because required dependency $modkey with build ID $(UUID(modbuild_id)) is missing from the cache."
@goto check_next_path
@label check_next_dep
end
M = get(loaded_precompiles, pkg => newbuild_id, nothing)
if isa(M, Module)
stalecheck && register_root_module(M)
return M
end
if stalecheck
try
touch(path_to_try) # update timestamp of precompilation file
catch ex # file might be read-only and then we fail to update timestamp, which is fine
ex isa IOError || rethrow()
end
end
end
for build_id in try_build_ids
for path_to_try in paths::Vector{String}
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try; reasons, stalecheck)
if staledeps === true
continue
end
# finish loading module graph into staledeps
# TODO: call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock
for i in eachindex(staledeps)
dep = staledeps[i]
dep isa Module && continue
modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep::Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}}
dep = start_loading(modkey, modbuild_id, stalecheck)
while true
if dep isa Module
if PkgId(dep) == modkey && module_build_id(dep) === modbuild_id
break
else
@debug "Rejecting cache file $path_to_try because module $modkey got loaded at a different version than expected."
@goto check_next_path
try
staledeps, ocachefile, newbuild_id = staledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
# finish checking staledeps module graph
for i in eachindex(staledeps)
dep = staledeps[i]
dep isa Module && continue
modpath, modkey, modbuild_id = dep::Tuple{String, PkgId, UInt128}
modpaths = find_all_in_cache_path(modkey, DEPOT_PATH)
for modpath_to_try in modpaths
modstaledeps = stale_cachefile(modkey, modbuild_id, modpath, modpath_to_try; stalecheck)
if modstaledeps === true
continue
end
modstaledeps, modocachepath, _ = modstaledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128}
staledeps[i] = (modpath, modkey, modbuild_id, modpath_to_try, modstaledeps, modocachepath)
@goto check_next_dep
end
@debug "Rejecting cache file $path_to_try because required dependency $modkey with build ID $(UUID(modbuild_id)) is missing from the cache."
@goto check_next_path
@label check_next_dep
end
M = maybe_loaded_precompile(pkg, newbuild_id)
if isa(M, Module)
stalecheck && register_root_module(M)
return M
end
if stalecheck
try
touch(path_to_try) # update timestamp of precompilation file
catch ex # file might be read-only and then we fail to update timestamp, which is fine
ex isa IOError || rethrow()
end
if dep === nothing
try
set_pkgorigin_version_path(modkey, modpath)
dep = _include_from_serialized(modkey, modcachepath, modocachepath, modstaledeps; register = stalecheck)
finally
end_loading(modkey, dep)
end
# finish loading module graph into staledeps
# TODO: call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock
for i in eachindex(staledeps)
dep = staledeps[i]
dep isa Module && continue
modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep::Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}}
dep = start_loading(modkey, modbuild_id, stalecheck)
while true
if dep isa Module
if PkgId(dep) == modkey && module_build_id(dep) === modbuild_id
break
else
@debug "Rejecting cache file $path_to_try because module $modkey got loaded at a different version than expected."
@goto check_next_path
end
end
if !isa(dep, Module)
@debug "Rejecting cache file $path_to_try because required dependency $modkey failed to load from cache file for $modcachepath." exception=dep
@goto check_next_path
else
push!(newdeps, modkey)
if dep === nothing
try
set_pkgorigin_version_path(modkey, modpath)
dep = _include_from_serialized(modkey, modcachepath, modocachepath, modstaledeps; register = stalecheck)
finally
end_loading(modkey, dep)
end
if !isa(dep, Module)
@debug "Rejecting cache file $path_to_try because required dependency $modkey failed to load from cache file for $modcachepath." exception=dep
@goto check_next_path
else
push!(newdeps, modkey)
end
end
end
staledeps[i] = dep
end
staledeps[i] = dep
end
restored = get(loaded_precompiles, pkg => newbuild_id, nothing)
if !isa(restored, Module)
restored = _include_from_serialized(pkg, path_to_try, ocachefile, staledeps; register = stalecheck)
end
isa(restored, Module) && return restored
@debug "Deserialization checks failed while attempting to load cache from $path_to_try" exception=restored
@label check_next_path
finally
for modkey in newdeps
insert_extension_triggers(modkey)
stalecheck && run_package_callbacks(modkey)
restored = maybe_loaded_precompile(pkg, newbuild_id)
if !isa(restored, Module)
restored = _include_from_serialized(pkg, path_to_try, ocachefile, staledeps; register = stalecheck)
end
isa(restored, Module) && return restored
@debug "Deserialization checks failed while attempting to load cache from $path_to_try" exception=restored
@label check_next_path
finally
for modkey in newdeps
insert_extension_triggers(modkey)
stalecheck && run_package_callbacks(modkey)
end
empty!(newdeps)
end
empty!(newdeps)
end
end
return nothing
Expand All @@ -2047,7 +2060,7 @@ function start_loading(modkey::PkgId, build_id::UInt128, stalecheck::Bool)
loaded = stalecheck ? maybe_root_module(modkey) : nothing
loaded isa Module && return loaded
if build_id != UInt128(0)
loaded = get(loaded_precompiles, modkey => build_id, nothing)
loaded = maybe_loaded_precompile(modkey, build_id)
loaded isa Module && return loaded
end
loading = get(package_locks, modkey, nothing)
Expand Down Expand Up @@ -2377,12 +2390,21 @@ const pkgorigins = Dict{PkgId,PkgOrigin}()

const explicit_loaded_modules = Dict{PkgId,Module}() # Emptied on Julia start
const loaded_modules = Dict{PkgId,Module}() # available to be explicitly loaded
const loaded_precompiles = Dict{Pair{PkgId,UInt128},Module}() # extended (complete) list of modules, available to be loaded
const loaded_precompiles = Dict{PkgId,Vector{Module}}() # extended (complete) list of modules, available to be loaded
const loaded_modules_order = Vector{Module}()
const module_keys = IdDict{Module,PkgId}() # the reverse of loaded_modules

root_module_key(m::Module) = @lock require_lock module_keys[m]

function maybe_loaded_precompile(key::PkgId, buildid::UInt128)
assert_havelock(require_lock)
mods = get(loaded_precompiles, key, nothing)
mods === nothing && return
for mod in mods
module_build_id(mod) == buildid && return mod
end
end

function module_build_id(m::Module)
hi, lo = ccall(:jl_module_build_id, NTuple{2,UInt64}, (Any,), m)
return (UInt128(hi) << 64) | lo
Expand All @@ -2403,7 +2425,7 @@ end
end
end
end
haskey(loaded_precompiles, key => module_build_id(m)) || push!(loaded_modules_order, m)
maybe_loaded_precompile(key, module_build_id(m)) === nothing && push!(loaded_modules_order, m)
loaded_modules[key] = m
explicit_loaded_modules[key] = m
module_keys[m] = key
Expand Down Expand Up @@ -3789,8 +3811,8 @@ end
for i in 1:ndeps
req_key, req_build_id = required_modules[i]
# Check if module is already loaded
if !stalecheck && haskey(loaded_precompiles, req_key => req_build_id)
M = loaded_precompiles[req_key => req_build_id]
M = stalecheck ? nothing : maybe_loaded_precompile(req_key, req_build_id)
if M !== nothing
@assert PkgId(M) == req_key && module_build_id(M) === req_build_id
depmods[i] = M
elseif root_module_exists(req_key)
Expand Down
7 changes: 5 additions & 2 deletions base/timing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function time_print(io::IO, elapsedtime, bytes=0, gctime=0, allocs=0, lock_confl
print(io, length(timestr) < 10 ? (" "^(10 - length(timestr))) : "")
end
print(io, timestr, " seconds")
parens = bytes != 0 || allocs != 0 || gctime > 0 || compile_time > 0 || lock_conflicts > 0
parens = bytes != 0 || allocs != 0 || gctime > 0 || lock_conflicts > 0 || compile_time > 0
parens && print(io, " (")
if bytes != 0 || allocs != 0
allocs, ma = prettyprint_getunits(allocs, length(_cnt_units), Int64(1000))
Expand All @@ -224,8 +224,11 @@ function time_print(io::IO, elapsedtime, bytes=0, gctime=0, allocs=0, lock_confl
print(io, Ryu.writefixed(Float64(100*gctime/elapsedtime), 2), "% gc time")
end
if lock_conflicts > 0
if bytes != 0 || allocs != 0 || gctime > 0
print(io, ", ")
end
plural = lock_conflicts == 1 ? "" : "s"
print(io, ", ", lock_conflicts, " lock conflict$plural")
print(io, lock_conflicts, " lock conflict$plural")
end
if compile_time > 0
if bytes != 0 || allocs != 0 || gctime > 0 || lock_conflicts > 0
Expand Down
7 changes: 1 addition & 6 deletions stdlib/Mmap/src/Mmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ function mmap(io::IO,
szfile = convert(Csize_t, len + offset)
requestedSizeLarger = false
if !(io isa Mmap.Anonymous)
@static if !Sys.isapple()
requestedSizeLarger = szfile > filesize(io)
end
requestedSizeLarger = szfile > filesize(io)
end
# platform-specific mmapping
@static if Sys.isunix()
Expand All @@ -231,9 +229,6 @@ function mmap(io::IO,
throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
end
end
@static if Sys.isapple()
iswrite && grow && grow!(io, offset, len)
end
# mmap the file
ptr = ccall(:jl_mmap, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Cint, Cint, RawFD, Int64),
C_NULL, mmaplen, prot, flags, file_desc, offset_page)
Expand Down
17 changes: 17 additions & 0 deletions test/compiler/EscapeAnalysis/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2299,4 +2299,21 @@ let result = code_escapes((SafeRef{String},Any)) do x, y
@test has_all_escape(result.state[Argument(3)]) # y
end

@eval function scope_folding()
$(Expr(:tryfinally,
Expr(:block,
Expr(:tryfinally, :(), :(), 2),
:(return Core.current_scope())),
:(), 1))
end
@eval function scope_folding_opt()
$(Expr(:tryfinally,
Expr(:block,
Expr(:tryfinally, :(), :(), :(Base.inferencebarrier(2))),
:(return Core.current_scope())),
:(), :(Base.inferencebarrier(1))))
end
@test (@code_escapes scope_folding()) isa EAUtils.EscapeResult
@test (@code_escapes scope_folding_opt()) isa EAUtils.EscapeResult

end # module test_EA
7 changes: 2 additions & 5 deletions test/compiler/irpasses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,6 @@ let # lifting `isa` through Core.ifelse
@test count(iscall((src, isa)), src.code) == 0
end


let # lifting `isdefined` through PhiNode
src = code_typed1((Bool,Some{Int},)) do c, x
y = c ? x : nothing
Expand Down Expand Up @@ -1035,8 +1034,7 @@ exc39508 = ErrorException("expected")
end
@test test39508() === exc39508

let
# `typeassert` elimination after SROA
let # `typeassert` elimination after SROA
# NOTE we can remove this optimization once inference is able to reason about memory-effects
src = @eval Module() begin
mutable struct Foo; x; end
Expand All @@ -1051,8 +1049,7 @@ let
@test count(iscall((src, typeassert)), src.code) == 0
end

let
# Test for https://github.com/JuliaLang/julia/issues/43402
let # Test for https://github.com/JuliaLang/julia/issues/43402
# Ensure that structs required not used outside of the ccall,
# still get listed in the ccall_preserves

Expand Down
Loading

0 comments on commit e6eef3c

Please sign in to comment.