Skip to content

Commit 1ade7fd

Browse files
committed
wip: lookup inlined MethodInstance from parent debuginfo
1 parent 4c521c9 commit 1ade7fd

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

base/stacktraces.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,31 @@ Base.@constprop :none function lookup(pointer::Ptr{Cvoid})
109109
infos = @ccall jl_lookup_code_address(pointer::Ptr{Cvoid}, false::Cint)::Core.SimpleVector
110110
pointer = convert(UInt64, pointer)
111111
isempty(infos) && return [StackFrame(empty_sym, empty_sym, -1, nothing, true, false, pointer)] # this is equal to UNKNOWN
112-
res = Vector{StackFrame}(undef, length(infos))
113-
for i in 1:length(infos)
112+
ninfos = length(infos)
113+
res = Vector{StackFrame}(undef, ninfos)
114+
local debuginfo = false
115+
for i = ninfos:-1:1
114116
info = infos[i]::Core.SimpleVector
115117
@assert(length(info) == 6)
116118
func = info[1]::Symbol
117119
file = info[2]::Symbol
118120
linenum = info[3]::Int
119121
linfo = info[4]
120122
if linfo isa Core.CodeInstance
123+
if debuginfo === false
124+
debuginfo = linfo.debuginfo
125+
else
126+
debuginfo = true
127+
end
121128
linfo = linfo.def
129+
elseif debuginfo isa Core.DebugInfo
130+
# TODO lookup a program counter `pc` at the parent frame and use `buildLineInfoNode(debuginfo, nothing, pc)`
131+
if length(debuginfo.edges) == 1 # XXX
132+
debuginfo = debuginfo.edges[1]
133+
linfo = debuginfo.def
134+
else
135+
debuginfo = true
136+
end
122137
end
123138
res[i] = StackFrame(func, file, linenum, linfo, info[5]::Bool, info[6]::Bool, pointer)
124139
end

test/stacktraces.jl

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ can_inline = Bool(Base.JLOptions().can_inline)
9292
for (frame, func, inlined) in zip(trace, [g,h,f], (can_inline, can_inline, false))
9393
@test frame.func === typeof(func).name.mt.name
9494
# broken until #50082 can be addressed
95-
@test frame.linfo.def.module === which(func, (Any,)).module broken=inlined
96-
@test frame.linfo.def === which(func, (Any,)) broken=inlined
97-
@test frame.linfo.specTypes === Tuple{typeof(func), Int} broken=inlined
95+
@test frame.linfo.def.module === which(func, (Any,)).module
96+
@test frame.linfo.def === which(func, (Any,))
97+
@test frame.linfo.specTypes === Tuple{typeof(func), Int}
9898
# line
9999
@test frame.file === Symbol(@__FILE__)
100100
@test !frame.from_c
@@ -266,3 +266,61 @@ end
266266
@testset "Base.StackTraces docstrings" begin
267267
@test isempty(Docs.undocumented_names(StackTraces))
268268
end
269+
270+
global f_parent1_line::Int, f_inner1_line::Int, f_innermost1_line::Int
271+
function f_parent1(a)
272+
x = a
273+
return begin
274+
@inline f_inner1(x)
275+
end
276+
end; f_parent1_line = (@__LINE__) - 2
277+
function f_inner1(a)
278+
x = a
279+
return @inline f_innermost1(x)
280+
end; f_inner1_line = (@__LINE__) - 1
281+
f_innermost1(x) = x > 0 ? @noinline(sin(x)) : error("x is negative")
282+
f_innermost1_line = (@__LINE__) - 1
283+
let st = try
284+
f_parent1(-1)
285+
catch err
286+
stacktrace(catch_backtrace())
287+
end
288+
@test any(st) do sf
289+
sf.func === :f_parent1 && sf.line == f_parent1_line && sf.linfo isa Core.MethodInstance
290+
end
291+
@test any(st) do sf
292+
sf.func === :f_inner1 && sf.line == f_inner1_line && sf.linfo isa Core.MethodInstance && sf.inlined
293+
end
294+
@test any(st) do sf
295+
sf.func === :f_innermost1 && sf.line == f_innermost1_line && sf.linfo isa Core.MethodInstance && sf.inlined
296+
end
297+
end
298+
299+
global f_parent2_line::Int, f_inner2_line::Int, f_innermost2_line::Int
300+
function f_parent2(a)
301+
x = identity(a)
302+
return begin
303+
@inline f_inner2(x)
304+
end
305+
end; f_parent2_line = (@__LINE__) - 2
306+
function f_inner2(a)
307+
x = identity(a)
308+
return @inline f_innermost2(x)
309+
end; f_inner2_line = (@__LINE__) - 1
310+
f_innermost2(x) = x > 0 ? @noinline(sin(x)) : error("x is negative")
311+
f_innermost2_line = (@__LINE__) - 1
312+
let st = try
313+
f_parent2(-1)
314+
catch err
315+
stacktrace(catch_backtrace())
316+
end
317+
@test any(st) do sf
318+
sf.func === :f_parent2 && sf.line == f_parent2_line && sf.linfo isa Core.MethodInstance
319+
end
320+
@test_broken any(st) do sf
321+
sf.func === :f_inner2 && sf.line == f_inner2_line && sf.linfo isa Core.MethodInstance && sf.inlined
322+
end
323+
@test_broken any(st) do sf
324+
sf.func === :f_innermost2 && sf.line == f_innermost2_line && sf.linfo isa Core.MethodInstance && sf.inlined
325+
end
326+
end

0 commit comments

Comments
 (0)