Skip to content

Commit ebc743a

Browse files
vtjnashaviatesk
authored andcommitted
changes needed to adapt to compressed line table format in Julia
For JuliaLang/julia#52415
1 parent 31253a0 commit ebc743a

File tree

5 files changed

+101
-32
lines changed

5 files changed

+101
-32
lines changed

src/construct.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ function prepare_framecode(method::Method, @nospecialize(argtypes); enter_genera
172172
if (!isempty(lenv) && (hasarg(isidentical(:llvmcall), code.code) ||
173173
hasarg(isidentical(Base.llvmcall), code.code) ||
174174
hasarg(a->is_global_ref(a, Base, :llvmcall), code.code))) ||
175-
hasarg(isidentical(:iolock_begin), code.code)
175+
hasarg(isidentical(:iolock_begin), code.code)
176176
return Compiled()
177177
end
178178
framecode = FrameCode(method, code; generator=generator)

src/interpret.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,14 +460,25 @@ function coverage_visit_line!(frame::Frame)
460460
pc, code = frame.pc, frame.framecode
461461
code.report_coverage || return
462462
src = code.src
463+
@static if VERSION v"1.12.0-DEV.173"
464+
lineinfo = linetable(src, pc)
465+
file, line = lineinfo.file, lineinfo.line
466+
if line != frame.last_codeloc
467+
file isa Symbol || (file = Symbol(file)::Symbol)
468+
@ccall jl_coverage_visit_line(file::Cstring, sizeof(file)::Csize_t, line::Cint)::Cvoid
469+
frame.last_codeloc = line
470+
end
471+
else # VERSION < v"1.12.0-DEV.173"
463472
codeloc = src.codelocs[pc]
464473
if codeloc != frame.last_codeloc && codeloc != 0
465474
linetable = src.linetable::Vector{Any}
466475
lineinfo = linetable[codeloc]::Core.LineInfoNode
467-
file, line = String(lineinfo.file), lineinfo.line
468-
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
476+
file, line = lineinfo.file, lineinfo.line
477+
file isa Symbol || (file = Symbol(file)::Symbol)
478+
@ccall jl_coverage_visit_line(file::Cstring, sizeof(file)::Csize_t, line::Cint)::Cvoid
469479
frame.last_codeloc = codeloc
470480
end
481+
end # @static if
471482
end
472483

473484
# For "profiling" where JuliaInterpreter spends its time. See the commented-out block

src/types.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,24 @@ function FrameCode(scope, src::CodeInfo; generator=false, optimize=true)
147147

148148
lt = linetable(src)
149149
unique_files = Set{Symbol}()
150+
@static if VERSION v"1.12.0-DEV.173"
151+
function pushuniquefiles!(unique_files::Set{Symbol}, lt)
152+
for edge in lt.edges
153+
pushuniquefiles!(unique_files, edge)
154+
end
155+
linetable = lt.linetable
156+
if linetable === nothing
157+
push!(unique_files, Base.IRShow.debuginfo_file1(lt))
158+
else
159+
pushuniquefiles!(unique_files, linetable)
160+
end
161+
end
162+
pushuniquefiles!(unique_files, lt)
163+
else # VERSION < v"1.12.0-DEV.173"
150164
for entry in lt
151165
push!(unique_files, entry.file)
152166
end
167+
end # @static if
153168

154169
framecode = FrameCode(scope, src, methodtables, breakpoints, slotnamelists, used, generator, report_coverage, unique_files)
155170
if scope isa Method
@@ -237,7 +252,7 @@ mutable struct Frame
237252
assignment_counter::Int64
238253
caller::Union{Frame,Nothing}
239254
callee::Union{Frame,Nothing}
240-
last_codeloc::Int32
255+
last_codeloc::Int
241256
end
242257
function Frame(framecode::FrameCode, framedata::FrameData, pc=1, caller=nothing)
243258
if length(junk_frames) > 0

src/utils.jl

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -258,38 +258,88 @@ end
258258

259259
# These getters improve inference since fieldtype(CodeInfo, :linetable)
260260
# and fieldtype(CodeInfo, :codelocs) are both Any
261-
const LineTypes = Union{LineNumberNode,Core.LineInfoNode}
261+
@static if VERSION v"1.12.0-DEV.173"
262+
const LineTypes = Union{LineNumberNode,Base.IRShow.LineInfoNode}
263+
else
264+
const LineTypes = Union{LineNumberNode,Core.LineInfoNode}
265+
end
262266
function linetable(arg)
263267
if isa(arg, Frame)
264268
arg = arg.framecode
265269
end
266270
if isa(arg, FrameCode)
267271
arg = arg.src
268272
end
269-
return (arg::CodeInfo).linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
273+
ci = arg::CodeInfo
274+
@static if VERSION v"1.12.0-DEV.173"
275+
return ci.debuginfo
276+
else # VERSION < v"1.12.0-DEV.173"
277+
return ci.linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
278+
end # @static if
270279
end
271-
_linetable(list::Vector, i::Integer) = list[i]::Union{Expr,LineTypes}
272280
function linetable(arg, i::Integer; macro_caller::Bool=false)::Union{Expr,LineTypes}
273281
lt = linetable(arg)
274-
lineinfo = _linetable(lt, i)
282+
@static if VERSION v"1.12.0-DEV.173"
283+
# TODO: decode the linetable at this frame efficiently by reimplementing this here
284+
# TODO: get the contextual name from the parent, rather than returning "n/a" (which breaks Cthulhu)
285+
return Base.IRShow.buildLineInfoNode(lt, :var"n/a", i)[1] # ignore all inlining / macro expansion / etc :(
286+
else # VERSION < v"1.12.0-DEV.173"
287+
lin = lt[i]::Union{Expr,LineTypes}
275288
if macro_caller
276-
while lineinfo isa Core.LineInfoNode && lineinfo.method === Symbol("macro expansion") && lineinfo.inlined_at != 0
277-
lineinfo = _linetable(lt, lineinfo.inlined_at)
289+
while lin isa Core.LineInfoNode && lin.method === Symbol("macro expansion") && lin.inlined_at != 0
290+
lin = lt[lin.inlined_at]::Union{Expr,LineTypes}
278291
end
279292
end
280-
return lineinfo
293+
return lin
294+
end # @static if
295+
end
296+
297+
@static if VERSION v"1.12.0-DEV.173"
298+
299+
function getlastline(arg)
300+
debuginfo = linetable(arg)
301+
while true
302+
ltnext = debuginfo.linetable
303+
ltnext === nothing && break
304+
debuginfo = ltnext
305+
end
306+
lastline = 0
307+
for k = 0:typemax(Int)
308+
codeloc = Core.Compiler.getdebugidx(debuginfo, k)
309+
line::Int = codeloc[1]
310+
line < 0 && break
311+
lastline = max(lastline, line)
312+
end
313+
return lastline
314+
end
315+
function codelocs(arg, i::Integer)
316+
debuginfo = linetable(arg)
317+
codeloc = Core.Compiler.getdebugidx(debuginfo, i)
318+
line::Int = codeloc[1]
319+
line < 0 && return 0# broken or disabled debug info?
320+
if line == 0 && codeloc[2] == 0
321+
return 0 # no line number update
322+
end
323+
return i
281324
end
282325

326+
else # VERSION < v"1.12.0-DEV.173"
327+
328+
getfirstline(arg) = getline(linetable(arg)[begin])
329+
getlastline(arg) = getline(linetable(arg)[end])
283330
function codelocs(arg)
284331
if isa(arg, Frame)
285332
arg = arg.framecode
286333
end
287334
if isa(arg, FrameCode)
288335
arg = arg.src
289336
end
290-
return (arg::CodeInfo).codelocs::Vector{Int32}
337+
ci = arg::CodeInfo
338+
return ci.codelocs
291339
end
292-
codelocs(arg, i::Integer) = codelocs(arg)[i] # for consistency with linetable (but no extra benefit here)
340+
codelocs(arg, i::Integer) = codelocs(arg)[i]
341+
342+
end # @static if
293343

294344
function lineoffset(framecode::FrameCode)
295345
offset = 0
@@ -302,9 +352,9 @@ function lineoffset(framecode::FrameCode)
302352
end
303353

304354
function getline(ln::Union{LineTypes,Expr})
305-
_getline(ln::LineTypes) = ln.line
306-
_getline(ln::Expr) = ln.args[1] # assuming ln.head === :line
307-
return Int(_getline(ln))::Int
355+
_getline(ln::LineTypes) = Int(ln.line)
356+
_getline(ln::Expr) = ln.args[1]::Int # assuming ln.head === :line
357+
return _getline(ln)
308358
end
309359
function getfile(ln::Union{LineTypes,Expr})
310360
_getfile(ln::LineTypes) = ln.file::Symbol
@@ -367,7 +417,7 @@ function codelocation(code::CodeInfo, idx::Int)
367417
idx′ = idx
368418
# look ahead if we are on a meta line
369419
while idx′ < length(code.code)
370-
codeloc = codelocs(code)[idx′]
420+
codeloc = codelocs(code, idx′)
371421
codeloc == 0 || return codeloc
372422
ex = code.code[idx′]
373423
ex === nothing || isexpr(ex, :meta) || break
@@ -377,7 +427,7 @@ function codelocation(code::CodeInfo, idx::Int)
377427
# if zero, look behind until we find where we last might have had a line
378428
while idx′ > 0
379429
ex = code.code[idx′]
380-
codeloc = codelocs(code)[idx′]
430+
codeloc = codelocs(code, idx′)
381431
codeloc == 0 || return codeloc
382432
idx′ -= 1
383433
end
@@ -390,13 +440,11 @@ function compute_corrected_linerange(method::Method)
390440
offset = line1 - method.line
391441
@assert !is_generated(method)
392442
src = JuliaInterpreter.get_source(method)
393-
lastline = linetable(src)[end]::LineTypes
394-
return line1:getline(lastline) + offset
443+
lastline = getlastline(src)
444+
return line1:lastline + offset
395445
end
396446

397-
function compute_linerange(framecode)
398-
getline(linetable(framecode, 1)):getline(last(linetable(framecode)))
399-
end
447+
compute_linerange(framecode) = getfirstline(framecode):getlastline(framecode)
400448

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

437-
438485
# If the exact line number does not exist in the line table, take the one that is closest after that line
439486
# restricted to the line range of the current scope.
440487
scope = framecode.scope
@@ -506,9 +553,7 @@ breakpointchar(framecode, stmtidx) =
506553
function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements(framecode), kwargs...)
507554
iscolor = get(io, :color, false)
508555
ndstmt = ndigits(nstatements(framecode))
509-
lt = linetable(framecode)
510-
offset = lineoffset(framecode)
511-
ndline = isempty(lt) ? 0 : ndigits(getline(lt[end]) + offset)
556+
ndline = ndigits(getlastline(framecode) + lineoffset(framecode))
512557
nullline = " "^ndline
513558
src = copy(framecode.src)
514559
replace_coretypes!(src; rev=true)
@@ -759,12 +804,11 @@ function Base.StackTraces.StackFrame(frame::Frame)
759804
Base.StackFrame(
760805
fname,
761806
Symbol(getfile(frame)),
762-
@something(linenumber(frame), getline(linetable(frame, 1))),
807+
@something(linenumber(frame), getfirstline(frame)),
763808
mi,
764809
false,
765810
false,
766-
C_NULL
767-
)
811+
C_NULL)
768812
end
769813

770814
function Base.show_backtrace(io::IO, frame::Frame)

test/utils.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ struct Aborted # for signaling that some statement or test blocks were interr
3636
end
3737

3838
function Aborted(frame::Frame, pc)
39-
src = frame.framecode.src
40-
lineidx = src.codelocs[pc]
39+
lineidx = JuliaInterpreter.codelocs(frame, pc)
4140
lineinfo = JuliaInterpreter.linetable(frame, lineidx; macro_caller=true)
4241
return Aborted(lineinfo)
4342
end

0 commit comments

Comments
 (0)