Skip to content

Commit

Permalink
wip: lookup inlined MethodInstance from parent debuginfo
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed Apr 3, 2024
1 parent 4c521c9 commit 1ade7fd
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 5 deletions.
19 changes: 17 additions & 2 deletions base/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,31 @@ Base.@constprop :none function lookup(pointer::Ptr{Cvoid})
infos = @ccall jl_lookup_code_address(pointer::Ptr{Cvoid}, false::Cint)::Core.SimpleVector
pointer = convert(UInt64, pointer)
isempty(infos) && return [StackFrame(empty_sym, empty_sym, -1, nothing, true, false, pointer)] # this is equal to UNKNOWN
res = Vector{StackFrame}(undef, length(infos))
for i in 1:length(infos)
ninfos = length(infos)
res = Vector{StackFrame}(undef, ninfos)
local debuginfo = false
for i = ninfos:-1:1
info = infos[i]::Core.SimpleVector
@assert(length(info) == 6)
func = info[1]::Symbol
file = info[2]::Symbol
linenum = info[3]::Int
linfo = info[4]
if linfo isa Core.CodeInstance
if debuginfo === false
debuginfo = linfo.debuginfo
else
debuginfo = true
end
linfo = linfo.def
elseif debuginfo isa Core.DebugInfo
# TODO lookup a program counter `pc` at the parent frame and use `buildLineInfoNode(debuginfo, nothing, pc)`
if length(debuginfo.edges) == 1 # XXX
debuginfo = debuginfo.edges[1]
linfo = debuginfo.def
else
debuginfo = true
end
end
res[i] = StackFrame(func, file, linenum, linfo, info[5]::Bool, info[6]::Bool, pointer)
end
Expand Down
64 changes: 61 additions & 3 deletions test/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ can_inline = Bool(Base.JLOptions().can_inline)
for (frame, func, inlined) in zip(trace, [g,h,f], (can_inline, can_inline, false))
@test frame.func === typeof(func).name.mt.name
# broken until #50082 can be addressed
@test frame.linfo.def.module === which(func, (Any,)).module broken=inlined
@test frame.linfo.def === which(func, (Any,)) broken=inlined
@test frame.linfo.specTypes === Tuple{typeof(func), Int} broken=inlined
@test frame.linfo.def.module === which(func, (Any,)).module
@test frame.linfo.def === which(func, (Any,))
@test frame.linfo.specTypes === Tuple{typeof(func), Int}
# line
@test frame.file === Symbol(@__FILE__)
@test !frame.from_c
Expand Down Expand Up @@ -266,3 +266,61 @@ end
@testset "Base.StackTraces docstrings" begin
@test isempty(Docs.undocumented_names(StackTraces))
end

global f_parent1_line::Int, f_inner1_line::Int, f_innermost1_line::Int
function f_parent1(a)
x = a
return begin
@inline f_inner1(x)
end
end; f_parent1_line = (@__LINE__) - 2
function f_inner1(a)
x = a
return @inline f_innermost1(x)
end; f_inner1_line = (@__LINE__) - 1
f_innermost1(x) = x > 0 ? @noinline(sin(x)) : error("x is negative")
f_innermost1_line = (@__LINE__) - 1
let st = try
f_parent1(-1)
catch err
stacktrace(catch_backtrace())
end
@test any(st) do sf
sf.func === :f_parent1 && sf.line == f_parent1_line && sf.linfo isa Core.MethodInstance
end
@test any(st) do sf
sf.func === :f_inner1 && sf.line == f_inner1_line && sf.linfo isa Core.MethodInstance && sf.inlined
end
@test any(st) do sf
sf.func === :f_innermost1 && sf.line == f_innermost1_line && sf.linfo isa Core.MethodInstance && sf.inlined
end
end

global f_parent2_line::Int, f_inner2_line::Int, f_innermost2_line::Int
function f_parent2(a)
x = identity(a)
return begin
@inline f_inner2(x)
end
end; f_parent2_line = (@__LINE__) - 2
function f_inner2(a)
x = identity(a)
return @inline f_innermost2(x)
end; f_inner2_line = (@__LINE__) - 1
f_innermost2(x) = x > 0 ? @noinline(sin(x)) : error("x is negative")
f_innermost2_line = (@__LINE__) - 1
let st = try
f_parent2(-1)
catch err
stacktrace(catch_backtrace())
end
@test any(st) do sf
sf.func === :f_parent2 && sf.line == f_parent2_line && sf.linfo isa Core.MethodInstance
end
@test_broken any(st) do sf
sf.func === :f_inner2 && sf.line == f_inner2_line && sf.linfo isa Core.MethodInstance && sf.inlined
end
@test_broken any(st) do sf
sf.func === :f_innermost2 && sf.line == f_innermost2_line && sf.linfo isa Core.MethodInstance && sf.inlined
end
end

0 comments on commit 1ade7fd

Please sign in to comment.