Skip to content

Commit 16b332c

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

File tree

5 files changed

+100
-26
lines changed

5 files changed

+100
-26
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: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,24 @@ function coverage_visit_line!(frame::Frame)
460460
pc, code = frame.pc, frame.framecode
461461
code.report_coverage || return
462462
src = code.src
463-
codeloc = src.codelocs[pc]
464-
if codeloc != frame.last_codeloc && codeloc != 0
465-
linetable = src.linetable::Vector{Any}
466-
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)
469-
frame.last_codeloc = codeloc
463+
@static if VERSION v"1.12.0-DEV.173"
464+
lineinfo = linetable(src.debuginfo, pc)
465+
file, line = lineinfo.file, lineinfo.line
466+
if line != frame.last_codeloc
467+
file isa Symbol || (file = Symbol(file))
468+
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
469+
frame.last_codeloc = codeloc
470+
end
471+
else
472+
codeloc = src.codelocs[pc]
473+
if codeloc != frame.last_codeloc && codeloc != 0
474+
linetable = src.linetable::Vector{Any}
475+
lineinfo = linetable[codeloc]::Core.LineInfoNode
476+
file, line = lineinfo.file, lineinfo.line
477+
file isa Symbol || (file = Symbol(file))
478+
ccall(:jl_coverage_visit_line, Cvoid, (Cstring, Csize_t, Cint), file, sizeof(file), line)
479+
frame.last_codeloc = codeloc
480+
end
470481
end
471482
end
472483

src/types.jl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,23 @@ function FrameCode(scope, src::CodeInfo; generator=false, optimize=true)
147147

148148
lt = linetable(src)
149149
unique_files = Set{Symbol}()
150-
for entry in lt
151-
push!(unique_files, entry.file)
150+
@static if VERSION v"1.12.0-DEV.173"
151+
function pushuniquefiles!(unique_files, 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
164+
for entry in lt
165+
push!(unique_files, entry.file)
166+
end
152167
end
153168

154169
framecode = FrameCode(scope, src, methodtables, breakpoints, slotnamelists, used, generator, report_coverage, unique_files)
@@ -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: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -258,26 +258,74 @@ 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 = 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
277+
return ci.linetable::Union{Vector{Core.LineInfoNode},Vector{Any}} # issue #264
278+
end
270279
end
271280
_linetable(list::Vector, i::Integer) = list[i]::Union{Expr,LineTypes}
272281
function linetable(arg, i::Integer; macro_caller::Bool=false)::Union{Expr,LineTypes}
273282
lt = linetable(arg)
274-
lineinfo = _linetable(lt, i)
275-
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)
283+
@static if VERSION v"1.12.0-DEV.173"
284+
# TODO: decode the linetable at this frame efficiently by reimplementing this here
285+
# TODO: get the contextual name from the parent, rather than returning "n/a" (which breaks Cthulhu)
286+
return Base.IRShow.buildLineInfoNode(lt, :var"n/a", i)[1] # ignore all inlining / macro expansion / etc :(
287+
else
288+
lineinfo = _linetable(lt, i)
289+
if macro_caller
290+
while lineinfo isa Core.LineInfoNode && lineinfo.method === Symbol("macro expansion") && lineinfo.inlined_at != 0
291+
lineinfo = _linetable(lt, lineinfo.inlined_at)
292+
end
278293
end
294+
return lineinfo
295+
end
296+
end
297+
298+
@static if VERSION v"1.12.0-DEV.173"
299+
function linetable_max(lt::Core.DebugInfo)
300+
while true
301+
ltnext = lt.linetable
302+
ltnext === nothing && break
303+
lt = ltnext
304+
end
305+
lastline = 0
306+
for k = 0:typemax(Int)
307+
codeloc = Base.IRShow.getdebugidx(lt, k)
308+
line::Int = codeloc[1]
309+
line < 0 && break
310+
lastline = max(lastline, line)
311+
end
312+
return lastline
313+
end
314+
function codelocs(arg, i::Integer)
315+
lt = linetable(arg)
316+
codeloc = Base.IRShow.getdebugidx(lt, i)
317+
line::Int = codeloc[1]
318+
line < 0 && return 0 # broken or disabled debug info?
319+
if line == 0 && codeloc[2] == 0
320+
return 0 # no line number update
279321
end
280-
return lineinfo
322+
return Int(i)
323+
end
324+
325+
else # VERSION ≥ v"1.12.0-DEV.173"
326+
327+
function linetable_max(lt::Vector)
328+
return getline(lt[end])
281329
end
282330

283331
function codelocs(arg)
@@ -289,7 +337,8 @@ function codelocs(arg)
289337
end
290338
return (arg::CodeInfo).codelocs::Vector{Int32}
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+
end # VERSION ≥ v"1.12.0-DEV.173"
293342

294343
function lineoffset(framecode::FrameCode)
295344
offset = 0
@@ -367,7 +416,7 @@ function codelocation(code::CodeInfo, idx::Int)
367416
idx′ = idx
368417
# look ahead if we are on a meta line
369418
while idx′ < length(code.code)
370-
codeloc = codelocs(code)[idx′]
419+
codeloc = codelocs(code, idx′)
371420
codeloc == 0 || return codeloc
372421
ex = code.code[idx′]
373422
ex === nothing || isexpr(ex, :meta) || break
@@ -377,7 +426,7 @@ function codelocation(code::CodeInfo, idx::Int)
377426
# if zero, look behind until we find where we last might have had a line
378427
while idx′ > 0
379428
ex = code.code[idx′]
380-
codeloc = codelocs(code)[idx′]
429+
codeloc = codelocs(code, idx′)
381430
codeloc == 0 || return codeloc
382431
idx′ -= 1
383432
end
@@ -390,8 +439,8 @@ function compute_corrected_linerange(method::Method)
390439
offset = line1 - method.line
391440
@assert !is_generated(method)
392441
src = JuliaInterpreter.get_source(method)
393-
lastline = linetable(src)[end]::LineTypes
394-
return line1:getline(lastline) + offset
442+
lastline = linetable_max(linetable(src))
443+
return line1:lastline + offset
395444
end
396445

397446
function compute_linerange(framecode)
@@ -508,7 +557,7 @@ function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements
508557
ndstmt = ndigits(nstatements(framecode))
509558
lt = linetable(framecode)
510559
offset = lineoffset(framecode)
511-
ndline = isempty(lt) ? 0 : ndigits(getline(lt[end]) + offset)
560+
ndline = ndigits(linetable_max(lt) + offset)
512561
nullline = " "^ndline
513562
src = copy(framecode.src)
514563
replace_coretypes!(src; rev=true)

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)