Skip to content

Commit bcac693

Browse files
timholyNHDaly
andauthored
Add pretty-printing for Core.Compiler.Timings objects (#38596)
* Add minimal printing for Core.Compiler.Timings.Timing These objects are huge when printed with `show_default`. This makes the printing very brief. More detail is available with with AbstractTrees.print_tree. * Add nice printing for Core.Compiler.Timings.InferenceFrameInfo This inlines the `Core.Const` args into the signature, which results in a very compact display of both the type and the value, when applicable. Co-authored-by: Nathan Daly <NHDaly@gmail.com>
1 parent 40e4796 commit bcac693

File tree

2 files changed

+79
-6
lines changed

2 files changed

+79
-6
lines changed

base/show.jl

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,33 @@ function show(io::IO, l::Core.MethodInstance)
999999
end
10001000
end
10011001

1002+
# These sometimes show up as Const-values in InferenceFrameInfo signatures
1003+
show(io::IO, r::Core.Compiler.UnitRange) = show(io, r.start : r.stop)
1004+
show(io::IO, mime::MIME{Symbol("text/plain")}, r::Core.Compiler.UnitRange) = show(io, mime, r.start : r.stop)
1005+
1006+
function show(io::IO, mi_info::Core.Compiler.Timings.InferenceFrameInfo)
1007+
mi = mi_info.mi
1008+
def = mi.def
1009+
if isa(def, Method)
1010+
if isdefined(def, :generator) && mi === def.generator
1011+
print(io, "InferenceFrameInfo generator for ")
1012+
show(io, def)
1013+
else
1014+
print(io, "InferenceFrameInfo for ")
1015+
argnames = [isa(a, Core.Const) ? (isa(a.val, Type) ? "" : a.val) : "" for a in mi_info.slottypes[1:mi_info.nargs]]
1016+
show_tuple_as_call(io, def.name, mi.specTypes, false, nothing, argnames, true)
1017+
end
1018+
else
1019+
linetable = mi.uninferred.linetable
1020+
line = isempty(linetable) ? "" : (lt = linetable[1]; string(lt.file) * ':' * string(lt.line))
1021+
print(io, "Toplevel InferenceFrameInfo thunk from ", def, " starting at ", line)
1022+
end
1023+
end
1024+
1025+
function show(io::IO, tinf::Core.Compiler.Timings.Timing)
1026+
print(io, "Core.Compiler.Timings.Timing(", tinf.mi_info, ") with ", length(tinf.children), " children")
1027+
end
1028+
10021029
function show_delim_array(io::IO, itr::Union{AbstractArray,SimpleVector}, op, delim, cl,
10031030
delim_one, i1=first(LinearIndices(itr)), l=last(LinearIndices(itr)))
10041031
print(io, op)
@@ -2103,11 +2130,14 @@ end
21032130

21042131
# show the called object in a signature, given its type `ft`
21052132
# `io` should contain the UnionAll env of the signature
2106-
function show_signature_function(io::IO, @nospecialize(ft), demangle=false, fargname="", html=false)
2133+
function show_signature_function(io::IO, @nospecialize(ft), demangle=false, fargname="", html=false, qualified=false)
21072134
uw = unwrap_unionall(ft)
21082135
if ft <: Function && isa(uw, DataType) && isempty(uw.parameters) &&
21092136
isdefined(uw.name.module, uw.name.mt.name) &&
21102137
ft == typeof(getfield(uw.name.module, uw.name.mt.name))
2138+
if qualified && !is_exported_from_stdlib(uw.name.mt.name, uw.name.module) && uw.name.module !== Main
2139+
print_within_stacktrace(io, uw.name.module, '.', bold=true)
2140+
end
21112141
s = sprint(show_sym, (demangle ? demangle_function_name : identity)(uw.name.mt.name), context=io)
21122142
print_within_stacktrace(io, s, bold=true)
21132143
elseif isa(ft, DataType) && ft.name === Type.body.name &&
@@ -2135,7 +2165,7 @@ function print_within_stacktrace(io, s...; color=:normal, bold=false)
21352165
end
21362166
end
21372167

2138-
function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwargs=nothing, argnames=nothing)
2168+
function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwargs=nothing, argnames=nothing, qualified=false)
21392169
# print a method signature tuple for a lambda definition
21402170
if sig === Tuple
21412171
print(io, demangle ? demangle_function_name(name) : name, "(...)")
@@ -2149,7 +2179,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwa
21492179
sig = sig.body
21502180
end
21512181
sig = (sig::DataType).parameters
2152-
show_signature_function(env_io, sig[1], demangle)
2182+
show_signature_function(env_io, sig[1], demangle, "", false, qualified)
21532183
first = true
21542184
print_within_stacktrace(io, "(", bold=true)
21552185
show_argnames = argnames !== nothing && length(argnames) == length(sig)

test/compiler/inference.jl

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,6 +2879,7 @@ end
28792879
timing1 = time_inference() do
28802880
@eval M.g(2, 3.0)
28812881
end
2882+
@test occursin(r"Core.Compiler.Timings.Timing\(InferenceFrameInfo for Core.Compiler.Timings.ROOT\(\)\) with \d+ children", sprint(show, timing1))
28822883
# The last two functions to be inferred should be `i` and `i2`, inferred at runtime with
28832884
# their concrete types.
28842885
@test sort([mi_info.mi.def.name for (time,mi_info) in flatten_times(timing1)[end-1:end]]) == [:i, :i2]
@@ -2889,6 +2890,23 @@ end
28892890
@eval M.g(2, 3.0)
28902891
end
28912892
@test length(flatten_times(timing2)) < length(flatten_times(timing1))
2893+
# Printing of InferenceFrameInfo for mi.def isa Module
2894+
@eval module M
2895+
i(x) = x+5
2896+
i2(x) = x+2
2897+
h(a::Array) = i2(a[1]::Integer) + i(a[1]::Integer) + 2
2898+
g(y::Integer, x) = h(Any[y]) + Int(x)
2899+
end
2900+
# BEGIN LINE NUMBER SENSITIVITY (adjust the line offset below as needed)
2901+
timingmod = time_inference() do
2902+
@eval @testset "Outer" begin
2903+
@testset "Inner" begin
2904+
for i = 1:2 M.g(2, 3.0) end
2905+
end
2906+
end
2907+
end
2908+
@test occursin("thunk from $(@__MODULE__) starting at $(@__FILE__):$((@__LINE__) - 5)", string(timingmod.children))
2909+
# END LINE NUMBER SENSITIVITY
28922910

28932911
# Recursive function
28942912
@eval module _Recursive f(n::Integer) = n == 0 ? 0 : f(n-1) + 1 end
@@ -2903,12 +2921,38 @@ end
29032921
i(x) = x === 0 ? 0 : 1 / x
29042922
a(x) = i(0) * i(x)
29052923
b() = i(0) * i(1) * i(0)
2924+
function loopc(n)
2925+
s = 0
2926+
for i = 1:n
2927+
s += i
2928+
end
2929+
return s
2930+
end
2931+
call_loopc() = loopc(5)
2932+
myfloor(::Type{T}, x) where T = floor(T, x)
2933+
d(x) = myfloor(Int16, x)
29062934
end
29072935
timing = time_inference() do
29082936
@eval C.a(2)
29092937
@eval C.b()
2910-
end
2911-
@test !isempty(flatten_times(timing))
2938+
@eval C.call_loopc()
2939+
@eval C.d(3.2)
2940+
end
2941+
ft = flatten_times(timing)
2942+
@test !isempty(ft)
2943+
str = sprint(show, ft)
2944+
@test occursin("InferenceFrameInfo for /(1::$Int, ::$Int)", str) # inference constants
2945+
@test occursin("InferenceFrameInfo for Core.Compiler.Timings.ROOT()", str) # qualified
2946+
# loopc has internal slots, check constant printing in this case
2947+
sel = filter(ti -> ti.second.mi.def.name === :loopc, ft)
2948+
ifi = sel[end].second
2949+
@test length(ifi.slottypes) > ifi.nargs
2950+
str = sprint(show, sel)
2951+
@test occursin("InferenceFrameInfo for $(@__MODULE__).C.loopc(5::$Int)", str)
2952+
# check that types aren't double-printed as `T::Type{T}`
2953+
sel = filter(ti -> ti.second.mi.def.name === :myfloor, ft)
2954+
str = sprint(show, sel)
2955+
@test occursin("InferenceFrameInfo for $(@__MODULE__).C.myfloor(::Type{Int16}, ::Float64)", str)
29122956
end
29132957

29142958
# issue #37638
@@ -2919,4 +2963,3 @@ f37943(x::Any, i::Int) = getfield((x::Pair{false, Int}), i)
29192963
g37943(i::Int) = fieldtype(Pair{false, T} where T, i)
29202964
@test only(Base.return_types(f37943, Tuple{Any, Int})) === Union{}
29212965
@test only(Base.return_types(g37943, Tuple{Int})) === Union{Type{Union{}}, Type{Any}}
2922-

0 commit comments

Comments
 (0)