Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes to adapt to compressed line table format #606

Merged
merged 1 commit into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/construct.jl
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ function prepare_framecode(method::Method, @nospecialize(argtypes); enter_genera
if (!isempty(lenv) && (hasarg(isidentical(:llvmcall), code.code) ||
hasarg(isidentical(Base.llvmcall), code.code) ||
hasarg(a->is_global_ref(a, Base, :llvmcall), code.code))) ||
hasarg(isidentical(:iolock_begin), code.code)
hasarg(isidentical(:iolock_begin), code.code)
return Compiled()
end
framecode = FrameCode(method, code; generator=generator)
Expand Down
15 changes: 13 additions & 2 deletions src/interpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,25 @@
pc, code = frame.pc, frame.framecode
code.report_coverage || return
src = code.src
@static if VERSION ≥ v"1.12.0-DEV.173"
lineinfo = linetable(src, pc)
file, line = lineinfo.file, lineinfo.line
if line != frame.last_codeloc
file isa Symbol || (file = Symbol(file)::Symbol)
@ccall jl_coverage_visit_line(file::Cstring, sizeof(file)::Csize_t, line::Cint)::Cvoid
frame.last_codeloc = line

Check warning on line 469 in src/interpret.jl

View check run for this annotation

Codecov / codecov/patch

src/interpret.jl#L463-L469

Added lines #L463 - L469 were not covered by tests
end
else # VERSION < v"1.12.0-DEV.173"
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)
file, line = lineinfo.file, lineinfo.line
file isa Symbol || (file = Symbol(file)::Symbol)
@ccall jl_coverage_visit_line(file::Cstring, sizeof(file)::Csize_t, line::Cint)::Cvoid

Check warning on line 478 in src/interpret.jl

View check run for this annotation

Codecov / codecov/patch

src/interpret.jl#L476-L478

Added lines #L476 - L478 were not covered by tests
frame.last_codeloc = codeloc
end
end # @static if
end

# For "profiling" where JuliaInterpreter spends its time. See the commented-out block
Expand Down
17 changes: 16 additions & 1 deletion src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,24 @@

lt = linetable(src)
unique_files = Set{Symbol}()
@static if VERSION ≥ v"1.12.0-DEV.173"

Check warning on line 150 in src/types.jl

View check run for this annotation

Codecov / codecov/patch

src/types.jl#L150

Added line #L150 was not covered by tests
function pushuniquefiles!(unique_files::Set{Symbol}, 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 # VERSION < v"1.12.0-DEV.173"
for entry in lt
push!(unique_files, entry.file)
end
end # @static if

framecode = FrameCode(scope, src, methodtables, breakpoints, slotnamelists, used, generator, report_coverage, unique_files)
if scope isa Method
Expand Down Expand Up @@ -237,7 +252,7 @@
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
96 changes: 70 additions & 26 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -258,38 +258,88 @@

# These getters improve inference since fieldtype(CodeInfo, :linetable)
# and fieldtype(CodeInfo, :codelocs) are both Any
const LineTypes = Union{LineNumberNode,Core.LineInfoNode}
@static if VERSION ≥ v"1.12.0-DEV.173"
const LineTypes = Union{LineNumberNode,Base.IRShow.LineInfoNode}
else
const LineTypes = Union{LineNumberNode,Core.LineInfoNode}
end
function linetable(arg)
if isa(arg, Frame)
arg = arg.framecode
end
if isa(arg, FrameCode)
arg = arg.src
end
return (arg::CodeInfo).linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
ci = arg::CodeInfo
@static if VERSION ≥ v"1.12.0-DEV.173"

Check warning on line 274 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L274

Added line #L274 was not covered by tests
return ci.debuginfo
else # VERSION < v"1.12.0-DEV.173"
return ci.linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
end # @static if
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)
@static if VERSION ≥ v"1.12.0-DEV.173"

Check warning on line 282 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L282

Added line #L282 was not covered by tests
# 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 # VERSION < v"1.12.0-DEV.173"
lin = lt[i]::Union{Expr,LineTypes}
if macro_caller
while lineinfo isa Core.LineInfoNode && lineinfo.method === Symbol("macro expansion") && lineinfo.inlined_at != 0
lineinfo = _linetable(lt, lineinfo.inlined_at)
while lin isa Core.LineInfoNode && lin.method === Symbol("macro expansion") && lin.inlined_at != 0
lin = lt[lin.inlined_at]::Union{Expr,LineTypes}
end
end
return lineinfo
return lin
end # @static if
end

@static if VERSION ≥ v"1.12.0-DEV.173"

function getlastline(arg)
debuginfo = linetable(arg)
while true
ltnext = debuginfo.linetable
ltnext === nothing && break
debuginfo = ltnext
end
lastline = 0
for k = 0:typemax(Int)
codeloc = Core.Compiler.getdebugidx(debuginfo, k)
line::Int = codeloc[1]
line < 0 && break
lastline = max(lastline, line)
end
return lastline

Check warning on line 313 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L299-L313

Added lines #L299 - L313 were not covered by tests
end
function codelocs(arg, i::Integer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For statementnumbers to function in v1.12, there's a need for a tool that can rebuild the full codelocs object from Core.DebugInfo, similar to what we could do just by looking at src.codelocs previously. Or, we may have to overhaul the statementnumbers algorithm.

debuginfo = linetable(arg)
codeloc = Core.Compiler.getdebugidx(debuginfo, 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

Check warning on line 321 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L315-L321

Added lines #L315 - L321 were not covered by tests
end
return i

Check warning on line 323 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L323

Added line #L323 was not covered by tests
end

else # VERSION < v"1.12.0-DEV.173"

getfirstline(arg) = getline(linetable(arg)[begin])
getlastline(arg) = getline(linetable(arg)[end])
function codelocs(arg)
if isa(arg, Frame)
arg = arg.framecode
end
if isa(arg, FrameCode)
arg = arg.src
end
return (arg::CodeInfo).codelocs::Vector{Int32}
ci = arg::CodeInfo
return ci.codelocs
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 # @static if

function lineoffset(framecode::FrameCode)
offset = 0
Expand All @@ -302,9 +352,9 @@
end

function getline(ln::Union{LineTypes,Expr})
_getline(ln::LineTypes) = ln.line
_getline(ln::Expr) = ln.args[1] # assuming ln.head === :line
return Int(_getline(ln))::Int
_getline(ln::LineTypes) = Int(ln.line)
_getline(ln::Expr) = ln.args[1]::Int # assuming ln.head === :line

Check warning on line 356 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L356

Added line #L356 was not covered by tests
return _getline(ln)
end
function getfile(ln::Union{LineTypes,Expr})
_getfile(ln::LineTypes) = ln.file::Symbol
Expand Down Expand Up @@ -367,7 +417,7 @@
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 +427,7 @@
# 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,13 +440,11 @@
offset = line1 - method.line
@assert !is_generated(method)
src = JuliaInterpreter.get_source(method)
lastline = linetable(src)[end]::LineTypes
return line1:getline(lastline) + offset
lastline = getlastline(src)
return line1:lastline + offset
end

function compute_linerange(framecode)
getline(linetable(framecode, 1)):getline(last(linetable(framecode)))
end
compute_linerange(framecode) = getfirstline(framecode):getlastline(framecode)

function statementnumbers(framecode::FrameCode, line::Integer, file::Symbol)
# Check to see if this framecode really contains that line. Methods that fill in a default positional argument,
Expand Down Expand Up @@ -434,7 +482,6 @@
return stmtidxs
end


# If the exact line number does not exist in the line table, take the one that is closest after that line
# restricted to the line range of the current scope.
scope = framecode.scope
Expand Down Expand Up @@ -506,9 +553,7 @@
function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements(framecode), kwargs...)
iscolor = get(io, :color, false)
ndstmt = ndigits(nstatements(framecode))
lt = linetable(framecode)
offset = lineoffset(framecode)
ndline = isempty(lt) ? 0 : ndigits(getline(lt[end]) + offset)
ndline = ndigits(getlastline(framecode) + lineoffset(framecode))
nullline = " "^ndline
src = copy(framecode.src)
replace_coretypes!(src; rev=true)
Expand Down Expand Up @@ -759,12 +804,11 @@
Base.StackFrame(
fname,
Symbol(getfile(frame)),
@something(linenumber(frame), getline(linetable(frame, 1))),
@something(linenumber(frame), getfirstline(frame)),
mi,
false,
false,
C_NULL
)
C_NULL)
end

function Base.show_backtrace(io::IO, frame::Frame)
Expand Down
3 changes: 1 addition & 2 deletions test/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ struct Aborted # for signaling that some statement or test blocks were interr
end

function Aborted(frame::Frame, pc)
src = frame.framecode.src
lineidx = src.codelocs[pc]
lineidx = JuliaInterpreter.codelocs(frame, pc)
lineinfo = JuliaInterpreter.linetable(frame, lineidx; macro_caller=true)
return Aborted(lineinfo)
end
Expand Down
Loading