From a49297b3b72fbdfad9e4a2db571e09e5a429ceb5 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 06:17:35 -0500 Subject: [PATCH 1/9] Support PrecompileTools on nightly xref https://github.com/JuliaLang/julia/pull/57074 The old `Compiler.Timings` infrastructure is disabled, so here we leverage the same `newly_compiled` infrastructure used during precompilation. --- Project.toml | 4 +- src/PrecompileTools.jl | 17 +-- src/workloads.jl | 73 +++------- test/PC_A/src/PC_A.jl | 6 +- test/runtests.jl | 297 ++++++++++++++++++++--------------------- 5 files changed, 167 insertions(+), 230 deletions(-) diff --git a/Project.toml b/Project.toml index 3f0c8a3..34a5224 100644 --- a/Project.toml +++ b/Project.toml @@ -1,14 +1,14 @@ name = "PrecompileTools" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" authors = ["Tim Holy ", "t-bltg ", "and contributors"] -version = "1.2.1" +version = "1.3.0" [deps] Preferences = "21216c6a-2e73-6563-6e65-726566657250" [compat] Preferences = "1" -julia = "1" +julia = "1.12" [extras] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" diff --git a/src/PrecompileTools.jl b/src/PrecompileTools.jl index 6b8625d..c76a98b 100644 --- a/src/PrecompileTools.jl +++ b/src/PrecompileTools.jl @@ -1,27 +1,18 @@ module PrecompileTools -if VERSION >= v"1.6" - using Preferences -end +using Preferences + export @setup_workload, @compile_workload, @recompile_invalidations const verbose = Ref(false) # if true, prints all the precompiles -const have_inference_tracking = isdefined(Core.Compiler, :__set_measure_typeinf) -const have_force_compile = isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("#@force_compile")) -function precompile_mi(mi) +function precompile_mi(mi::Core.MethodInstance) precompile(mi.specTypes) # TODO: Julia should allow one to pass `mi` directly (would handle `invoke` properly) verbose[] && println(mi) return end include("workloads.jl") -if VERSION >= v"1.9.0-rc2" - include("invalidations.jl") -else - macro recompile_invalidations(ex::Expr) - return esc(ex) - end -end +include("invalidations.jl") end diff --git a/src/workloads.jl b/src/workloads.jl index 373c3af..0480b1b 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -1,3 +1,4 @@ +const newly_inferred = Core.CodeInstance[] function workload_enabled(mod::Module) try @@ -11,30 +12,12 @@ function workload_enabled(mod::Module) end end -""" - check_edges(node) - -Recursively ensure that all callees of `node` are precompiled. This is (rarely) necessary -because sometimes there is no backedge from callee to caller (xref https://github.com/JuliaLang/julia/issues/49617), -and `staticdata.c` relies on the backedge to trace back to a MethodInstance that is tagged `mi.precompiled`. -""" -function check_edges(node) - parentmi = node.mi_info.mi - for child in node.children - childmi = child.mi_info.mi - if !(isdefined(childmi, :backedges) && parentmi ∈ childmi.backedges) - precompile_mi(childmi) - end - check_edges(child) - end -end - -function precompile_roots(roots) - @assert have_inference_tracking - for child in roots - precompile_mi(child.mi_info.mi) - check_edges(child) +function precompile_newly_inferred(cis) + while !isempty(cis) + ci = pop!(cis) + precompile_mi(ci.def) end + return cis end """ @@ -66,37 +49,21 @@ end - indirect runtime-dispatched calls to such methods. """ macro compile_workload(ex::Expr) - local iscompiling = if Base.VERSION < v"1.6" - :(ccall(:jl_generating_output, Cint, ()) == 1) - else - :((ccall(:jl_generating_output, Cint, ()) == 1 && $PrecompileTools.workload_enabled(@__MODULE__))) - end - if have_force_compile - ex = quote - begin - Base.Experimental.@force_compile - $(esc(ex)) - end - end - else - # Use the hack on earlier Julia versions that blocks the interpreter - ex = quote - while false end + local iscompiling = :((ccall(:jl_generating_output, Cint, ()) == 1 && $PrecompileTools.workload_enabled(@__MODULE__))) + ex = quote + begin + Base.Experimental.@force_compile $(esc(ex)) end end - if have_inference_tracking - ex = quote - Core.Compiler.Timings.reset_timings() - Core.Compiler.__set_measure_typeinf(true) - try - $ex - finally - Core.Compiler.__set_measure_typeinf(false) - Core.Compiler.Timings.close_current_timer() - end - $PrecompileTools.precompile_roots(Core.Compiler.Timings._timings[1].children) + ex = quote + ccall(:jl_set_newly_inferred, Cvoid, (Any,), newly_inferred) + try + $ex + finally + ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) end + $PrecompileTools.precompile_newly_inferred(newly_inferred) end return quote if $iscompiling || $PrecompileTools.verbose[] @@ -128,11 +95,7 @@ runtime dispatches (though they will be precompiled anyway if the runtime-callee to your package). """ macro setup_workload(ex::Expr) - local iscompiling = if Base.VERSION < v"1.6" - :(ccall(:jl_generating_output, Cint, ()) == 1) - else - :((ccall(:jl_generating_output, Cint, ()) == 1 && $PrecompileTools.workload_enabled(@__MODULE__))) - end + local iscompiling = :((ccall(:jl_generating_output, Cint, ()) == 1 && $PrecompileTools.workload_enabled(@__MODULE__))) # Ideally we'd like a `let` around this to prevent namespace pollution, but that seem to # trigger inference & codegen in undesirable ways (see #16). return quote diff --git a/test/PC_A/src/PC_A.jl b/test/PC_A/src/PC_A.jl index 86ce09f..e524ab6 100644 --- a/test/PC_A/src/PC_A.jl +++ b/test/PC_A/src/PC_A.jl @@ -6,11 +6,7 @@ struct MyType x::Int end -if isdefined(Base, :inferencebarrier) - inferencebarrier(@nospecialize(arg)) = Base.inferencebarrier(arg) -else - inferencebarrier(@nospecialize(arg)) = Ref{Any}(arg)[] -end +inferencebarrier(@nospecialize(arg)) = Base.inferencebarrier(arg) function call_findfirst(x, list) # call a method defined in Base by runtime dispatch diff --git a/test/runtests.jl b/test/runtests.jl index a829bf7..b4c0d94 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,192 +2,179 @@ using PrecompileTools using Test using Pkg using UUIDs +using Base: specializations @testset "PrecompileTools.jl" begin - specializations(m::Method) = isdefined(Base, :specializations) ? Base.specializations(m) : m.specializations - push!(LOAD_PATH, @__DIR__) using PC_A - if VERSION >= v"1.8" - # Check that calls inside @setup_workload are not precompiled - m = which(Tuple{typeof(Base.vect), Vararg{T}} where T) - have_mytype = false - for mi in specializations(m) - mi === nothing && continue - have_mytype |= Base.unwrap_unionall(mi.specTypes).parameters[2] === PC_A.MyType - end - have_mytype && @warn "Code in setup_workload block was precompiled" - # Check that calls inside @compile_workload are precompiled - m = only(methods(PC_A.call_findfirst)) - count = 0 - for mi in specializations(m) - mi === nothing && continue - sig = Base.unwrap_unionall(mi.specTypes) - if sig.parameters[2] == PC_A.MyType && sig.parameters[3] == Vector{PC_A.MyType} - count += 1 - end - end - @test count == 1 - # Even one that was runtime-dispatched - m = which(Tuple{typeof(findfirst), Base.Fix2{typeof(==), T}, Vector{T}} where T) - count = 0 - for mi in specializations(m) - mi === nothing && continue - sig = Base.unwrap_unionall(mi.specTypes) - if sig.parameters[3] == Vector{PC_A.MyType} - count += 1 - end + # Check that calls inside @setup_workload are not precompiled + m = which(Tuple{typeof(Base.vect), Vararg{T}} where T) + have_mytype = false + for mi in specializations(m) + mi === nothing && continue + have_mytype |= Base.unwrap_unionall(mi.specTypes).parameters[2] === PC_A.MyType + end + have_mytype && @warn "Code in setup_workload block was precompiled" + # Check that calls inside @compile_workload are precompiled + m = only(methods(PC_A.call_findfirst)) + count = 0 + for mi in specializations(m) + mi === nothing && continue + sig = Base.unwrap_unionall(mi.specTypes) + if sig.parameters[2] == PC_A.MyType && sig.parameters[3] == Vector{PC_A.MyType} + count += 1 end - @test count == 1 end - - if VERSION >= v"1.7" # so we can use redirect_stderr(f, ::Pipe) - pipe = Pipe() - id = Base.PkgId(UUID("d38b61e7-59a2-4ef9-b4d3-320bdc69b817"), "PC_B") - redirect_stderr(pipe) do - @test_throws Exception Base.require(id) + @test count == 1 + # Even one that was runtime-dispatched + m = which(Tuple{typeof(findfirst), Base.Fix2{typeof(==), T}, Vector{T}} where T) + count = 0 + for mi in specializations(m) + mi === nothing && continue + sig = Base.unwrap_unionall(mi.specTypes) + if sig.parameters[3] == Vector{PC_A.MyType} + count += 1 end - close(pipe.in) - str = read(pipe.out, String) - @test occursin(r"UndefVarError: `?missing_function`? not defined", str) end + @test count == 1 - if VERSION >= v"1.6" - using PC_C + pipe = Pipe() + id = Base.PkgId(UUID("d38b61e7-59a2-4ef9-b4d3-320bdc69b817"), "PC_B") + redirect_stderr(pipe) do + @test_throws Exception Base.require(id) end + close(pipe.in) + str = read(pipe.out, String) + @test occursin(r"UndefVarError: `?missing_function`? not defined", str) - if VERSION >= v"1.6" - script = """ - using PC_D - exit(isdefined(PC_D, :workload_ran) === parse(Bool, ARGS[1]) ? 0 : 1) - """ + using PC_C - projfile = Base.active_project() - Pkg.activate("PC_D") - Pkg.instantiate() - using PC_D + script = """ + using PC_D + exit(isdefined(PC_D, :workload_ran) === parse(Bool, ARGS[1]) ? 0 : 1) + """ - PrecompileTools.Preferences.set_preferences!(PC_D, "precompile_workload" => false) - @test success(run(`$(Base.julia_cmd()) --project=$(joinpath(@__DIR__, "PC_D")) -e $script 0`)) + projfile = Base.active_project() + Pkg.activate("PC_D") + Pkg.instantiate() + using PC_D - PrecompileTools.Preferences.delete_preferences!(PC_D, "precompile_workload"; force = true) - @test success(run(`$(Base.julia_cmd()) --project=$(joinpath(@__DIR__, "PC_D")) -e $script 1`)) - Pkg.activate(projfile) - end + PrecompileTools.Preferences.set_preferences!(PC_D, "precompile_workload" => false) + @test success(run(`$(Base.julia_cmd()) --project=$(joinpath(@__DIR__, "PC_D")) -e $script 0`)) - if VERSION >= v"1.6" - oldval = PrecompileTools.verbose[] - PrecompileTools.verbose[] = true - mktemp() do path, io - redirect_stdout(io) do - include(joinpath(@__DIR__, "PC_E", "src", "PC_E.jl")) - end - close(io) - str = read(path, String) - @test occursin("MethodInstance for", str) - modscope = Base.VERSION >= v"1.7" ? "PC_E." : "" - @test occursin("$(modscope)f(::$Int)", str) - @test occursin("$(modscope)f(::String)", str) + PrecompileTools.Preferences.delete_preferences!(PC_D, "precompile_workload"; force = true) + @test success(run(`$(Base.julia_cmd()) --project=$(joinpath(@__DIR__, "PC_D")) -e $script 1`)) + Pkg.activate(projfile) + + oldval = PrecompileTools.verbose[] + PrecompileTools.verbose[] = true + mktemp() do path, io + redirect_stdout(io) do + include(joinpath(@__DIR__, "PC_E", "src", "PC_E.jl")) end - PrecompileTools.verbose[] = oldval + close(io) + str = read(path, String) + @test occursin("MethodInstance for", str) + modscope = "PC_E." + @test occursin("$(modscope)f(::$Int)", str) + @test occursin("$(modscope)f(::String)", str) end + PrecompileTools.verbose[] = oldval - if isdefined(PrecompileTools, :invalidation_leaves) - # Mimic the format written to `_jl_debug_method_invalidation` - # As a source of MethodInstances, `getproperty` has lots - m = which(getproperty, (Any, Symbol)) - mis = Core.MethodInstance[] - for mi in specializations(m) - length(mis) >= 10 && break - mi === nothing && continue - push!(mis, mi) - end - # These mimic the invalidation lists in SnoopCompile's `test/snoopr.jl` - invs = Any[mis[1], 0, mis[2], 1, Tuple{}, m, "jl_method_table_insert"] - @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2]]) - invs = Any[mis[1], 0, mis[2], 1, mis[3], 1, Tuple{}, m, "jl_method_table_insert"] - @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2], mis[3]]) - invs = Any[mis[1], 0, mis[2], 1, Tuple{}, mis[1], 1, mis[3], "jl_method_table_insert", m, "jl_method_table_insert"] - @test PrecompileTools.invalidation_leaves(invs) == Set(mis[1:3]) - invs = Any[mis[1], 1, mis[2], "jl_method_table_disable", m, "jl_method_table_disable"] - @test PrecompileTools.invalidation_leaves(invs) == Set([mis[1], mis[2]]) - invs = Any[mis[1], 1, mis[2], "jl_method_table_disable", mis[3], "jl_method_table_insert", m] - @test Set([mis[1], mis[2]]) ⊆ PrecompileTools.invalidation_leaves(invs) - invs = Any[mis[1], 1, mis[2], "jl_method_table_insert", mis[2], "invalidate_mt_cache", m, "jl_method_table_insert"] - @test PrecompileTools.invalidation_leaves(invs) == Set([mis[1], mis[2]]) - invs = Any[Tuple{}, "insert_backedges_callee", 55, Any[m], mis[2], "verify_methods", 55] - @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2]]) + # Mimic the format written to `_jl_debug_method_invalidation` + # As a source of MethodInstances, `getproperty` has lots + m = which(getproperty, (Any, Symbol)) + mis = Core.MethodInstance[] + for mi in specializations(m) + length(mis) >= 10 && break + mi === nothing && continue + push!(mis, mi) + end + # These mimic the invalidation lists in SnoopCompile's `test/snoopr.jl` + invs = Any[mis[1], 0, mis[2], 1, Tuple{}, m, "jl_method_table_insert"] + @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2]]) + invs = Any[mis[1], 0, mis[2], 1, mis[3], 1, Tuple{}, m, "jl_method_table_insert"] + @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2], mis[3]]) + invs = Any[mis[1], 0, mis[2], 1, Tuple{}, mis[1], 1, mis[3], "jl_method_table_insert", m, "jl_method_table_insert"] + @test PrecompileTools.invalidation_leaves(invs) == Set(mis[1:3]) + invs = Any[mis[1], 1, mis[2], "jl_method_table_disable", m, "jl_method_table_disable"] + @test PrecompileTools.invalidation_leaves(invs) == Set([mis[1], mis[2]]) + invs = Any[mis[1], 1, mis[2], "jl_method_table_disable", mis[3], "jl_method_table_insert", m] + @test Set([mis[1], mis[2]]) ⊆ PrecompileTools.invalidation_leaves(invs) + invs = Any[mis[1], 1, mis[2], "jl_method_table_insert", mis[2], "invalidate_mt_cache", m, "jl_method_table_insert"] + @test PrecompileTools.invalidation_leaves(invs) == Set([mis[1], mis[2]]) + invs = Any[Tuple{}, "insert_backedges_callee", 55, Any[m], mis[2], "verify_methods", 55] + @test PrecompileTools.invalidation_leaves(invs) == Set([mis[2]]) - # Add a real invalidation & repair test - cproj = Base.active_project() - mktempdir() do dir - push!(LOAD_PATH, dir) - cd(dir) do - for ((pkg1, pkg2, pkg3), recompile) in ((("RC_A", "RC_B", "RC_C"), false,), - (("RC_D", "RC_E", "RC_F"), true)) - Pkg.generate(pkg1) - open(joinpath(dir, pkg1, "src", pkg1*".jl"), "w") do io + # Add a real invalidation & repair test + cproj = Base.active_project() + mktempdir() do dir + push!(LOAD_PATH, dir) + cd(dir) do + for ((pkg1, pkg2, pkg3), recompile) in ((("RC_A", "RC_B", "RC_C"), false,), + (("RC_D", "RC_E", "RC_F"), true)) + Pkg.generate(pkg1) + open(joinpath(dir, pkg1, "src", pkg1*".jl"), "w") do io + println(io, """ + module $pkg1 + nbits(::Int8) = 8 + nbits(::Int16) = 16 + call_nbits(c) = nbits(only(c)) + begin + Base.Experimental.@force_compile + call_nbits(Any[Int8(5)]) + end + end + """) + end + Pkg.generate(pkg2) + Pkg.activate(joinpath(dir, pkg2)) + Pkg.develop(PackageSpec(path=joinpath(dir, pkg1))) + open(joinpath(dir, pkg2, "src", pkg2*".jl"), "w") do io + println(io, """ + module $pkg2 + using $pkg1 + $(pkg1).nbits(::Int32) = 32 + end + """) + end + # pkg3 is like a "Startup" package that recompiles the invalidations from loading the "code universe" + Pkg.generate(pkg3) + Pkg.activate(joinpath(dir, pkg3)) + Pkg.develop(PackageSpec(path=joinpath(dir, pkg2))) + Pkg.develop(PackageSpec(path=dirname(@__DIR__))) # depend on PrecompileTools + open(joinpath(dir, pkg3, "src", pkg3*".jl"), "w") do io + if recompile println(io, """ - module $pkg1 - nbits(::Int8) = 8 - nbits(::Int16) = 16 - call_nbits(c) = nbits(only(c)) - begin - Base.Experimental.@force_compile - call_nbits(Any[Int8(5)]) - end + module $pkg3 + using PrecompileTools + @recompile_invalidations using $pkg2 end """) - end - Pkg.generate(pkg2) - Pkg.activate(joinpath(dir, pkg2)) - Pkg.develop(PackageSpec(path=joinpath(dir, pkg1))) - open(joinpath(dir, pkg2, "src", pkg2*".jl"), "w") do io + else println(io, """ - module $pkg2 - using $pkg1 - $(pkg1).nbits(::Int32) = 32 + module $pkg3 + using PrecompileTools + using $pkg2 end """) end - # pkg3 is like a "Startup" package that recompiles the invalidations from loading the "code universe" - Pkg.generate(pkg3) - Pkg.activate(joinpath(dir, pkg3)) - Pkg.develop(PackageSpec(path=joinpath(dir, pkg2))) - Pkg.develop(PackageSpec(path=dirname(@__DIR__))) # depend on PrecompileTools - open(joinpath(dir, pkg3, "src", pkg3*".jl"), "w") do io - if recompile - println(io, """ - module $pkg3 - using PrecompileTools - @recompile_invalidations using $pkg2 - end - """) - else - println(io, """ - module $pkg3 - using PrecompileTools - using $pkg2 - end - """) - end - end - - @eval using $(Symbol(pkg3)) - mod3 = Base.@invokelatest getglobal(@__MODULE__, Symbol(pkg3)) - mod2 = Base.@invokelatest getglobal(mod3, Symbol(pkg2)) - mod1 = Base.@invokelatest getglobal(mod2, Symbol(pkg1)) - m = only(methods(mod1.call_nbits)) - mi = first(specializations(m)) - wc = Base.get_world_counter() - @test recompile ? mi.cache.max_world >= wc : mi.cache.max_world < wc end + + @eval using $(Symbol(pkg3)) + mod3 = Base.@invokelatest getglobal(@__MODULE__, Symbol(pkg3)) + mod2 = Base.@invokelatest getglobal(mod3, Symbol(pkg2)) + mod1 = Base.@invokelatest getglobal(mod2, Symbol(pkg1)) + m = only(methods(mod1.call_nbits)) + mi = first(specializations(m)) + wc = Base.get_world_counter() + @test recompile ? mi.cache.max_world >= wc : mi.cache.max_world < wc end - pop!(LOAD_PATH) end - Pkg.activate(cproj) + pop!(LOAD_PATH) end + Pkg.activate(cproj) pop!(LOAD_PATH) end From 77c092fe14b6e2553003dc4fc4e2743d10d6b032 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 06:22:06 -0500 Subject: [PATCH 2/9] Restrict CI --- .github/workflows/CI.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index baedc45..024be6b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,9 +18,7 @@ jobs: fail-fast: false matrix: version: - - '1.0' - - '1.6' - - '1' + - '1.12' - 'nightly' os: - ubuntu-latest From db9b9554c59c0b7cf10a9b027d41681bc10a0fce Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 13:14:02 -0500 Subject: [PATCH 3/9] Merge `Base.newly_inferred` and `newly_inferred` Co-authored-by: Jameson Nash --- src/workloads.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/workloads.jl b/src/workloads.jl index 0480b1b..cb63cdb 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -12,11 +12,15 @@ function workload_enabled(mod::Module) end end -function precompile_newly_inferred(cis) - while !isempty(cis) - ci = pop!(cis) - precompile_mi(ci.def) - end +@noinline function precompile_newly_inferred(cis) + ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) # ensure we drop internally references to both newly_inferred arrays so that it is safe to access them here + for child in cis # set the must-precompile bit on all new code + precompile_mi((child::Base.CodeInstance).def) + end + append!(Base.newly_inferred, cis) # request the new code be included in the serialized file + empty!(newly_inferred) + nothing +end return cis end From 49dc2d6aa75a610943ea3bc5aec1b7edea44f9cc Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 18 Mar 2025 14:17:08 -0400 Subject: [PATCH 4/9] Update workloads.jl --- src/workloads.jl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/workloads.jl b/src/workloads.jl index cb63cdb..6506c9e 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -13,15 +13,13 @@ function workload_enabled(mod::Module) end @noinline function precompile_newly_inferred(cis) - ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) # ensure we drop internally references to both newly_inferred arrays so that it is safe to access them here - for child in cis # set the must-precompile bit on all new code - precompile_mi((child::Base.CodeInstance).def) - end - append!(Base.newly_inferred, cis) # request the new code be included in the serialized file - empty!(newly_inferred) - nothing -end - return cis + ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) # ensure we drop internally references to both newly_inferred arrays so that it is safe to access them here + for child in cis # set the must-precompile bit on all new code + precompile_mi((child::Base.CodeInstance).def) + end + append!(Base.newly_inferred, cis) # request the new code be included in the serialized file + empty!(cis) + nothing end """ From 1cccfae6c1279d61d83f51b974dcac5d7fdc8e7f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 13:19:36 -0500 Subject: [PATCH 5/9] Update src/PrecompileTools.jl Co-authored-by: Jameson Nash --- src/PrecompileTools.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PrecompileTools.jl b/src/PrecompileTools.jl index c76a98b..17967dc 100644 --- a/src/PrecompileTools.jl +++ b/src/PrecompileTools.jl @@ -7,7 +7,7 @@ export @setup_workload, @compile_workload, @recompile_invalidations const verbose = Ref(false) # if true, prints all the precompiles function precompile_mi(mi::Core.MethodInstance) - precompile(mi.specTypes) # TODO: Julia should allow one to pass `mi` directly (would handle `invoke` properly) + precompile(mi) verbose[] && println(mi) return end From c7504f707dd23913cbced3156d8b6eea963f703d Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 13:28:30 -0500 Subject: [PATCH 6/9] Various fixes --- src/workloads.jl | 15 ++++++++------- test/runtests.jl | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/workloads.jl b/src/workloads.jl index 6506c9e..afccf4d 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -12,13 +12,15 @@ function workload_enabled(mod::Module) end end -@noinline function precompile_newly_inferred(cis) +cache_newly_inferred() = ccall(:jl_set_newly_inferred, Cvoid, (Any,), newly_inferred) + +@noinline function precompile_newly_inferred() ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) # ensure we drop internally references to both newly_inferred arrays so that it is safe to access them here - for child in cis # set the must-precompile bit on all new code + for child in newly_inferred # set the must-precompile bit on all new code precompile_mi((child::Base.CodeInstance).def) end - append!(Base.newly_inferred, cis) # request the new code be included in the serialized file - empty!(cis) + append!(Base.newly_inferred, newly_inferred) # request the new code be included in the serialized file + empty!(newly_inferred) nothing end @@ -59,13 +61,12 @@ macro compile_workload(ex::Expr) end end ex = quote - ccall(:jl_set_newly_inferred, Cvoid, (Any,), newly_inferred) + $PrecompileTools.cache_newly_inferred() try $ex finally - ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) + $PrecompileTools.precompile_newly_inferred() end - $PrecompileTools.precompile_newly_inferred(newly_inferred) end return quote if $iscompiling || $PrecompileTools.verbose[] diff --git a/test/runtests.jl b/test/runtests.jl index b4c0d94..8d42402 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,7 +22,7 @@ using Base: specializations for mi in specializations(m) mi === nothing && continue sig = Base.unwrap_unionall(mi.specTypes) - if sig.parameters[2] == PC_A.MyType && sig.parameters[3] == Vector{PC_A.MyType} + if sig == Tuple{typeof(PC_A.call_findfirst), PC_A.MyType, Vector{PC_A.MyType}} count += 1 end end From 039cd9d30796f93252ef47dd97feea6702e7374c Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 18 Mar 2025 13:40:56 -0500 Subject: [PATCH 7/9] Make the version happier --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3279887..3a638c9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,7 +18,7 @@ jobs: fail-fast: false matrix: version: - - '1.12' + - '1.12-nightly' # FIXME change to 1.12 when released - 'nightly' os: - ubuntu-latest From 04b53cd72bc7259d209bef0e59a65208d90291ab Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 19 Mar 2025 08:17:51 -0500 Subject: [PATCH 8/9] build docs on nightly --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3a638c9..07169d5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v2 with: - version: '1' + version: 'nightly' - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-docdeploy@v1 env: From ba242f198c986c1cc333e4fdb2261de7a9aa6a04 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 19 Mar 2025 08:18:20 -0500 Subject: [PATCH 9/9] Update to julia#57828 --- src/workloads.jl | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/workloads.jl b/src/workloads.jl index 7a8a19b..806f1f9 100644 --- a/src/workloads.jl +++ b/src/workloads.jl @@ -1,4 +1,4 @@ -const newly_inferred = Core.CodeInstance[] +const newly_inferred = Core.CodeInstance[] # only used to support verbose[] function workload_enabled(mod::Module) try @@ -12,16 +12,23 @@ function workload_enabled(mod::Module) end end -cache_newly_inferred() = ccall(:jl_set_newly_inferred, Cvoid, (Any,), newly_inferred) - -@noinline function precompile_newly_inferred() - ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) # ensure we drop internally references to both newly_inferred arrays so that it is safe to access them here - for child in newly_inferred # set the must-precompile bit on all new code - precompile_mi((child::Base.CodeInstance).def) +function tag_newly_inferred_enable() + ccall(:jl_tag_newly_inferred_enable, Cvoid, ()) + if !Base.generating_output() # for verbose[] + ccall(:jl_set_newly_inferred, Cvoid, (Any,), newly_inferred) + end +end +function tag_newly_inferred_disable() + ccall(:jl_tag_newly_inferred_disable, Cvoid, ()) + if !Base.generating_output() # for verbose[] + ccall(:jl_set_newly_inferred, Cvoid, (Any,), nothing) + end + if verbose[] + for ci in newly_inferred + println(ci.def) + end end - append!(Base.newly_inferred, newly_inferred) # request the new code be included in the serialized file - empty!(newly_inferred) - nothing + return nothing end """ @@ -61,11 +68,11 @@ macro compile_workload(ex::Expr) end end ex = quote - $PrecompileTools.cache_newly_inferred() + $PrecompileTools.tag_newly_inferred_enable() try $ex finally - $PrecompileTools.precompile_newly_inferred() + $PrecompileTools.tag_newly_inferred_disable() end end return quote