Skip to content

Consider generate_precompile prior to module close #38951

Open

Description

It's possible we should consider changing the strategy for the gen_precompile strategy; as noticed in #38906, not all statements are effectively precompilable. Here's a demo. First, if you precompile something that's well-and-truly compiled, it looks like this:

julia> mp = which(+, (Int, Int))
+(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:87

julia> mp.specializations[1]
MethodInstance for +(::Int64, ::Int64)

julia> mp.specializations[1].cache
Core.CodeInstance(MethodInstance for +(::Int64, ::Int64), #undef, 0x0000000000000001, 0xffffffffffffffff, Int64, #undef, UInt8[0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x16, 0x88  …  0x21, 0x53, 0x52, 0x2b, 0x57, 0x00, 0xbf, 0x3d, 0x01, 0x01], true, true, Ptr{Nothing} @0x00007f110804b7e0, Ptr{Nothing} @0x00007f110804b7d0)

julia> @time precompile(+, (Int, Int))
  0.000010 seconds (2 allocations: 144 bytes)
true

Now let's try another method:

julia> m = which(Base.uncompressed_ir, (Method,))
uncompressed_ir(m::Method) in Base at reflection.jl:984

julia> m.specializations[1]
MethodInstance for Base.uncompressed_ir(::Method)

julia> m.specializations[1].cache
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getproperty(x::Core.MethodInstance, f::Symbol)
   @ Base ./Base.jl:33
 [2] top-level scope
   @ REPL[7]:1

I'll show the time to precompile in a minute, but inspired by #32705 let's first peek at the method's roots:

julia> m.roots
6-element Vector{Any}:
 :(:source)
 :_uncompressed_ir
 :(:generator)
 "Method is @generated; try `code_lowered` instead."
 "Code for this Method is not available."
 :uncompressed_ir

julia> @time precompile(Base.uncompressed_ir, (Method,))
  0.011541 seconds (4.87 k allocations: 320.187 KiB, 99.91% compilation time)
true

Definitely not truly precompiled. And sure enough:

julia> m.roots
16-element Vector{Any}:
 :(:source)
 :_uncompressed_ir
 :(:generator)
 "Method is @generated; try `code_lowered` instead."
 "Code for this Method is not available."
 :uncompressed_ir
 typeof(isa)
 MethodInstance for copy(::Core.CodeInfo)
 :(:jl_uncompress_ir)
 :(:ccall)
 :($(QuoteNode(Ptr{Nothing} @0x0000000000000000)))
 :CodeInfo
 MethodInstance for error(::String)
 Symbol("Base.jl")
 isa (built-in function)
 Ptr{Nothing} @0x0000000000000000

The roots table expanded after compiling it, due to inlining its callees.

A way to solve this would to be to have our precompile generator emit statements before the final end of the module definition. That's a pretty big change in how we do this, of course; it would be worth discussing first whether #32705 can be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions