Skip to content

Commit

Permalink
changes needed to adapt to compressed line table format in Julia
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash authored and aviatesk committed Mar 21, 2024
1 parent 1b1b6d6 commit 3a9ae38
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 22 deletions.
25 changes: 18 additions & 7 deletions src/interpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,24 @@ function coverage_visit_line!(frame::Frame)
pc, code = frame.pc, frame.framecode
code.report_coverage || return
src = code.src
codeloc = src.codelocs[pc]
if codeloc != frame.last_codeloc && codeloc != 0
linetable = src.linetable::Vector{Any}
lineinfo = linetable[codeloc]::Core.LineInfoNode
file, line = String(lineinfo.file), lineinfo.line
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
frame.last_codeloc = codeloc
if isdefined(src, :debuginfo) # VERSION >= v"1.12"
lineinfo = linetable(src.debuginfo, pc)
file, line = lineinfo.file, lineinfo.line
if line != frame.last_codeloc
file isa Symbol || (file = Symbol(file))
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
frame.last_codeloc = codeloc
end
else
codeloc = src.codelocs[pc]
if codeloc != frame.last_codeloc && codeloc != 0
linetable = src.linetable::Vector{Any}
lineinfo = linetable[codeloc]::Core.LineInfoNode
file, line = lineinfo.file, lineinfo.line
file isa Symbol || (file = Symbol(file))
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
frame.last_codeloc = codeloc
end
end
end

Expand Down
21 changes: 18 additions & 3 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,23 @@ function FrameCode(scope, src::CodeInfo; generator=false, optimize=true)

lt = linetable(src)
unique_files = Set{Symbol}()
for entry in lt
push!(unique_files, entry.file)
if isdefined(src, :debuginfo) # VERSION >= v"1.12"
function pushuniquefiles!(unique_files, lt)
for edge in lt.edges
pushuniquefiles!(unique_files, edge)
end
linetable = lt.linetable
if linetable === nothing
push!(unique_files, Base.IRShow.debuginfo_file1(lt))
else
pushuniquefiles!(unique_files, linetable)
end
end
pushuniquefiles!(unique_files, lt)
else
for entry in lt
push!(unique_files, entry.file)
end
end

framecode = FrameCode(scope, src, methodtables, breakpoints, slotnamelists, used, generator, report_coverage, unique_files)
Expand Down Expand Up @@ -237,7 +252,7 @@ mutable struct Frame
assignment_counter::Int64
caller::Union{Frame,Nothing}
callee::Union{Frame,Nothing}
last_codeloc::Int32
last_codeloc::Int
end
function Frame(framecode::FrameCode, framedata::FrameData, pc=1, caller=nothing)
if length(junk_frames) > 0
Expand Down
69 changes: 57 additions & 12 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,18 +266,62 @@ function linetable(arg)
if isa(arg, FrameCode)
arg = arg.src
end
return (arg::CodeInfo).linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
ci = arg::CodeInfo
if isdefined(ci, :debuginfo) # VERSION >= v1.12
return ci.debuginfo
else
return ci.linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
end
end
_linetable(list::Vector, i::Integer) = list[i]::Union{Expr,LineTypes}
function linetable(arg, i::Integer; macro_caller::Bool=false)::Union{Expr,LineTypes}
lt = linetable(arg)
lineinfo = _linetable(lt, i)
if macro_caller
while lineinfo isa Core.LineInfoNode && lineinfo.method === Symbol("macro expansion") && lineinfo.inlined_at != 0
lineinfo = _linetable(lt, lineinfo.inlined_at)
if isdefined(Core, :DebugInfo)
# TODO: decode the linetable at this frame efficiently by reimplementing this here
# TODO: get the contextual name from the parent, rather than returning "n/a" (which breaks Cthulhu)
return Base.IRShow.buildLineInfoNode(lt, :var"n/a", i)[1] # ignore all inlining / macro expansion / etc :(
else
lineinfo = _linetable(lt, i)
if macro_caller
while lineinfo isa Core.LineInfoNode && lineinfo.method === Symbol("macro expansion") && lineinfo.inlined_at != 0
lineinfo = _linetable(lt, lineinfo.inlined_at)
end
end
return lineinfo
end
end

if isdefined(Core, :DebugInfo)
function linetable_max(lt::Core.DebugInfo)
while true
ltnext = lt.linetable
ltnext === nothing && break
lt = ltnext
end
lastline = 0
for k = 0:typemax(Int)
codeloc = Base.IRShow.getdebugidx(lt, k)
line::Int = codeloc[1]
line < 0 && break
lastline = max(lastline, line)
end
return lineinfo
return lastline
end
function codelocs(arg, i::Integer)
lt = linetable(arg)
codeloc = Base.IRShow.getdebugidx(lt, i)
line::Int = codeloc[1]
line < 0 && return 0 # broken or disabled debug info?
if line == 0 && codeloc[2] == 0
return 0 # no line number update
end
return Int(i)
end

else

function linetable_max(lt::Vector)
return getline(lt[end])
end

function codelocs(arg)
Expand All @@ -289,7 +333,8 @@ function codelocs(arg)
end
return (arg::CodeInfo).codelocs::Vector{Int32}
end
codelocs(arg, i::Integer) = codelocs(arg)[i] # for consistency with linetable (but no extra benefit here)
codelocs(arg, i::Integer) = codelocs(arg)[i]
end

function lineoffset(framecode::FrameCode)
offset = 0
Expand Down Expand Up @@ -367,7 +412,7 @@ function codelocation(code::CodeInfo, idx::Int)
idx′ = idx
# look ahead if we are on a meta line
while idx′ < length(code.code)
codeloc = codelocs(code)[idx′]
codeloc = codelocs(code, idx′)
codeloc == 0 || return codeloc
ex = code.code[idx′]
ex === nothing || isexpr(ex, :meta) || break
Expand All @@ -377,7 +422,7 @@ function codelocation(code::CodeInfo, idx::Int)
# if zero, look behind until we find where we last might have had a line
while idx′ > 0
ex = code.code[idx′]
codeloc = codelocs(code)[idx′]
codeloc = codelocs(code, idx′)
codeloc == 0 || return codeloc
idx′ -= 1
end
Expand All @@ -390,8 +435,8 @@ function compute_corrected_linerange(method::Method)
offset = line1 - method.line
@assert !is_generated(method)
src = JuliaInterpreter.get_source(method)
lastline = linetable(src)[end]::LineTypes
return line1:getline(lastline) + offset
lastline = linetable_max(linetable(src))
return line1:lastline + offset
end

function compute_linerange(framecode)
Expand Down Expand Up @@ -508,7 +553,7 @@ function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements
ndstmt = ndigits(nstatements(framecode))
lt = linetable(framecode)
offset = lineoffset(framecode)
ndline = isempty(lt) ? 0 : ndigits(getline(lt[end]) + offset)
ndline = ndigits(linetable_max(lt) + offset)
nullline = " "^ndline
src = copy(framecode.src)
replace_coretypes!(src; rev=true)
Expand Down

0 comments on commit 3a9ae38

Please sign in to comment.