Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions base/lock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,6 @@ mutable struct OncePerProcess{T, F} <: Function

function OncePerProcess{T,F}(initializer::F) where {T, F}
once = new{T,F}(nothing, PerStateInitial, true, initializer, ReentrantLock())
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :value, nothing)
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :state, PerStateInitial)
return once
end
end
Expand All @@ -721,6 +717,10 @@ OncePerProcess(initializer) = OncePerProcess{Base.promote_op(initializer), typeo
try
state = @atomic :monotonic once.state
if state == PerStateInitial
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :value, nothing)
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :state, PerStateInitial)
once.value = once.initializer()
elseif state == PerStateErrored
error("OncePerProcess initializer failed previously")
Expand Down Expand Up @@ -809,10 +809,6 @@ mutable struct OncePerThread{T, F} <: Function
function OncePerThread{T,F}(initializer::F) where {T, F}
xs, ss = AtomicMemory{T}(), AtomicMemory{UInt8}()
once = new{T,F}(xs, ss, initializer)
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :xs, xs)
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :ss, ss)
return once
end
end
Expand Down Expand Up @@ -849,6 +845,12 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
ss = @atomic :monotonic once.ss
xs = @atomic :monotonic once.xs
if tid > length(ss)
if length(ss) == 0 # We are the first to initialize
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :xs, xs)
ccall(:jl_set_precompile_field_replace, Cvoid, (Any, Any, Any),
once, :ss, ss)
end
@assert len <= length(ss) <= length(newss) "logical constraint violation"
fill_monotonic!(newss, PerStateInitial)
xs = copyto_monotonic!(newxs, xs)
Expand Down
56 changes: 53 additions & 3 deletions test/compileall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,60 @@
# We make it a separate test target here, so that it can run in parallel
# with the rest of the tests.

mktempdir() do dir
@test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'exit()'`, stderr=stderr)) skip=(Sys.WORD_SIZE == 32)
function precompile_test_harness(@nospecialize(f))
load_path = mktempdir()
try
pushfirst!(LOAD_PATH, load_path)
pushfirst!(DEPOT_PATH, load_path)
f(load_path)
finally
try
rm(load_path, force=true, recursive=true)
catch err
@show err
end
filter!((≠)(load_path), LOAD_PATH)
filter!((≠)(load_path), DEPOT_PATH)
end
return nothing
end

precompile_test_harness() do dir
Foo_file = joinpath(dir, "OncePerFoo.jl")
image_file = joinpath(dir, "img.jl")
write(Foo_file,
"""module OncePerFoo

const f = OncePerThread{Nothing}() do
println(Core.stdout, "Running thread init...")
end

f() # Executed during pre-compilation

end # module OncePerFoo
""")

write(image_file,
"""
Base.init_depot_path()
Base.init_load_path()
using OncePerFoo

function main()
OncePerFoo.f()
return 0
end

OncePerFoo.f() # fire init during compilation time

""")
Base.compilecache(Base.PkgId("OncePerFoo"))
new_env = Dict(["JULIA_DEPOT_PATH" => join(DEPOT_PATH, Sys.iswindows() ? ';' : ':'),
"JULIA_LOAD_PATH" => join(LOAD_PATH, Sys.iswindows() ? ';' : ':')])
@test success(pipeline(addenv(`$(Base.julia_cmd()) --compile=all -t1,0 --strip-ir --output-o $(dir)/sys.o.a $(image_file) `, new_env), stderr=stderr, stdout=stdout)) skip=(Sys.WORD_SIZE == 32)
if isfile(joinpath(dir, "sys.o.a"))
Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so"))
@test success(`$(Base.julia_cmd()) -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); exit()'`)
str = readchomp(`$(Base.julia_cmd()) -t1,0 -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); println("loaded"); main()'`)
@test split(str, '\n') == ["loaded", "Running thread init..."]
end
end