Description
openedon Dec 20, 2020
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.