Skip to content

Consider generate_precompile prior to module close #38951

Open
@timholy

Description

@timholy

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.

Metadata

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