Skip to content

Conversation

@vtjnash
Copy link
Member

@vtjnash vtjnash commented Feb 25, 2025

Reimplement all of the trim verification support in Julia as a compiler analysis pass. Move all this verification code into the Compiler julia code, where we have much better utilities for pretty printing and better observability for analysis.

julia> using Profile

julia> infos = Base.Compiler.typeinf_ext_toplevel(Any[Core.svec(Int, Tuple{typeof(Profile.take_heap_snapshot)})], [Base.get_world_counter()], true);
Verifier error #1: ccallable declared return type does not match inference for Tuple{typeof(Profile.take_heap_snapshot)} => String

Verifier error #2: unresolved call to builtin from (Core._call_latest)(Base.CoreLogging.shouldlog, (Base.CoreLogging.current_logger_for_env)(Base.CoreLogging.Warn, :Profile, Profile::Module)::Base.CoreLogging.AbstractLogger, $(QuoteNode(Warn)), $(QuoteNode(Profile)), :Profile, Profile.Symbol(φ ()::String)::Symbol)::Any
Stacktrace:
 [1] invokelatest(::typeof(Base.CoreLogging.shouldlog), ::Base.CoreLogging.AbstractLogger, ::Base.CoreLogging.LogLevel, ::Module, ::Symbol, ::Symbol; kwargs::@Kwargs{})
   @ Base essentials.jl:1057 [inlined]
 [2] invokelatest(::typeof(Base.CoreLogging.shouldlog), ::Base.CoreLogging.AbstractLogger, ::Base.CoreLogging.LogLevel, ::Module, ::Symbol, ::Symbol)
   @ Base essentials.jl:1053 [inlined]
 [3] macro expansion
   @ logging/logging.jl:405 [inlined]
 [4] take_heap_snapshot(all_one::Bool; dir::Nothing, kwargs::@Kwargs{})
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1463
 [5] take_heap_snapshot(all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1454 [inlined]

Verifier error #3: unresolved call to builtin from (Core._call_latest)(Base.CoreLogging.logging_error, φ ()::Base.CoreLogging.AbstractLogger, $(QuoteNode(Warn)), $(QuoteNode(Profile)), :Profile, φ ()::Symbol, φ ()::String, 1463, $(Expr(:the_exception))::Any, true::Bool)::Any
Stacktrace:
 [1] invokelatest(::typeof(Base.CoreLogging.logging_error), ::Base.CoreLogging.AbstractLogger, ::Base.CoreLogging.LogLevel, ::Module, ::Symbol, ::Symbol, ::String, ::Int64, ::Any, ::Bool; kwargs::@Kwargs{})
   @ Base essentials.jl:1057 [inlined]
 [2] invokelatest(::typeof(Base.CoreLogging.logging_error), ::Base.CoreLogging.AbstractLogger, ::Base.CoreLogging.LogLevel, ::Module, ::Symbol, ::Symbol, ::String, ::Int64, ::Any, ::Bool)
   @ Base essentials.jl:1053 [inlined]
 [3] macro expansion
   @ logging/logging.jl:387 [inlined]
 [4] take_heap_snapshot(all_one::Bool; dir::Nothing, kwargs::@Kwargs{})
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1463
 [5] take_heap_snapshot(all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1454 [inlined]

Verifier error #4: unresolved call from (f::Function)(%new()::IOBuffer, Core.getfield(args::Tuple{String}, 1)::String)::Any
Stacktrace:
 [1] sprint(f::Function, args::String; context::Nothing, sizehint::Int64)
   @ Base strings/io.jl:117
 [2] repr(x::String; context::Nothing)                                                                                                                                                                                                                                                                                  @ Base strings/io.jl:286 [inlined]
 [3] unsafe_convert(::Type{Cstring}, s::String)
   @ Base strings/cstring.jl:85 [inlined]
 [4] rm(path::String; force::Bool, recursive::Bool, allow_delayed_delete::Bool)
   @ Base.Filesystem file.jl:320
 [5] take_heap_snapshot(all_one::Bool; dir::Nothing, kwargs::@Kwargs{})
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1461
 [6] take_heap_snapshot(all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1454 [inlined]

Verifier error #5: unresolved call to function from Core._apply_iterate(Base.iterate, Base.open, args::Tuple{String, Vararg{String}})::IOStream
Stacktrace:
 [1] open(::Profile.HeapSnapshot.var"#assemble_snapshot##0#assemble_snapshot##1"{String}, ::String, ::Vararg{String}; kwargs::@Kwargs{})
   @ Base io.jl:408
 [2] open(::Profile.HeapSnapshot.var"#assemble_snapshot##0#assemble_snapshot##1"{String}, ::String, ::String)
   @ Base io.jl:407 [inlined]
 [3] assemble_snapshot(in_prefix::String, out_file::String)
   @ Profile.HeapSnapshot ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/heapsnapshot_reassemble.jl:81 [inlined]
 [4] take_heap_snapshot(filepath::String, all_one::Bool; redact_data::Bool, streaming::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1416
 [5] take_heap_snapshot(filepath::String, all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1408 [inlined]
 [6] take_heap_snapshot(all_one::Bool; dir::Nothing, kwargs::@Kwargs{})
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1469
 [7] take_heap_snapshot(all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1454 [inlined]

...

Verifier error #65: unresolved call from Base.pairs(@_2::NamedTuple)::Base.Pairs{Symbol, _A, I, A} where {_A, I<:Tuple{Vararg{Symbol}}, A<:NamedTuple}
Stacktrace:
 [1] macro expansion
   @ logging/logging.jl:388 [inlined]
 [2] take_heap_snapshot(all_one::Bool; dir::Nothing, kwargs::@Kwargs{})
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1463
 [3] take_heap_snapshot(all_one::Bool)
   @ Profile ~/julia/usr/share/julia/stdlib/v1.13/Profile/src/Profile.jl:1454 [inlined]

Trim verify finished with 1 warning.

Trim verify finished with 65 errors.

ERROR: verify_typeinf_trim failed
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:44
 [2] verify_typeinf_trim(io::Base.TTY, codeinfos::Vector{Any})
   @ Base.Compiler.TrimVerifier ./../usr/share/julia/Compiler/src/verifytrim.jl:326
 [3] #invokelatest#1
   @ ./essentials.jl:1057 [inlined]
 [4] invokelatest
   @ ./essentials.jl:1053 [inlined]
 [5] verify_typeinf_trim
   @ ./../usr/share/julia/Compiler/src/typeinfer.jl:1364 [inlined]
 [6] typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt64}, trim::Bool)
   @ Compiler ./../usr/share/julia/Compiler/src/typeinfer.jl:1359
 [7] top-level scope
   @ REPL[2]:1

Or with the whole trimming support:

$ JULIA_DEBUG=loading time ~/julia/julia -g0 -t1 -J ~/julia/usr/lib/julia/sys.so  --startup-file=no --history-file=no --output-o main.a --output-incremental=no --strip-ir --strip-metadata --experimental --trim ~/julia/contrib/juliac-buildscript.jl ~+/main.jl --output-exe true

@gbaraldi
Copy link
Member

I was in the process or writing this, I have like a third of it done but nice!

Move all this code into the Compiler julia code, where we have much
better utilities for printing and observability for analysis.
@vtjnash vtjnash force-pushed the jn/trim-verify-output branch from b8bb53f to db6f080 Compare February 25, 2025 22:48
@nsajko nsajko added the trimming Issues with trimming functionality or PR's relevant to its performance/functionality label Feb 26, 2025
const runtime_functions = Symbol[
# a denylist of any runtime functions which someone might ccall which can call jl_apply or access reflection state
# which might not be captured by the trim output
:jl_apply,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the list we have in alloc_check that we say can dispatch

"f__apply_latest", "f__apply_iterate", "f__apply_pure", "f__call_latest",
"f__call_in_world", "f__call_in_world_total", "f_intrinsic_call", "f_invoke",
"f_opaque_closure_call", "apply", "apply_generic", "gf_invoke",
"gf_invoke_by_method", "gf_invoke_lookup_worlds", "invoke", "invoke_api",
"call", "call0", "call1", "call2", "call3", "unknown_fptr"

@gbaraldi
Copy link
Member

The implementation looks quite good. One question I have is about if we can at least check for Tasks

@vtjnash
Copy link
Member Author

vtjnash commented Feb 26, 2025

Good call on that. That is the jl_new_task entrypoint, and so that does imply generic dispatch too. Shouldn't be much different from the other similar ones though. I'm thinking we should go ahead and merge this as-is today, and then work on fixing those other cases soon?

@vtjnash vtjnash added the backport 1.12 Change should be backported to release-1.12 label Feb 26, 2025
@vtjnash vtjnash merged commit 1045bd8 into master Feb 26, 2025
9 checks passed
@vtjnash vtjnash deleted the jn/trim-verify-output branch February 26, 2025 19:03
@Keno
Copy link
Member

Keno commented Feb 28, 2025

julia> @activate Compiler
Info Given Compiler was explicitly requested, output will be shown live
ERROR: LoadError: Method deletion is not possible during Module precompile.
Stacktrace:
  [1] delete_method(m::Method)
    @ Base ./runtime_internals.jl:1297
  [2] top-level scope
    @ ~/julia/Compiler/src/verifytrim.jl:314

KristofferC pushed a commit that referenced this pull request Mar 3, 2025
Reimplement all of the trim verification support in Julia as a compiler
analysis pass. Move all this verification code into the Compiler julia
code, where we have much better utilities for pretty printing and better
observability for analysis.

(cherry picked from commit 1045bd8)
topolarity added a commit that referenced this pull request Mar 6, 2025
KristofferC pushed a commit that referenced this pull request Mar 20, 2025
@KristofferC KristofferC removed the backport 1.12 Change should be backported to release-1.12 label Mar 24, 2025
serenity4 pushed a commit to serenity4/julia that referenced this pull request May 1, 2025
Reimplement all of the trim verification support in Julia as a compiler
analysis pass. Move all this verification code into the Compiler julia
code, where we have much better utilities for pretty printing and better
observability for analysis.
serenity4 pushed a commit to serenity4/julia that referenced this pull request May 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trimming Issues with trimming functionality or PR's relevant to its performance/functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants