Skip to content

Commit 2e37784

Browse files
committed
internals: support line-numbers describing a Method instead of just name
Not yet enabled, since we likely need to cache this more efficiently first.
1 parent c8510e3 commit 2e37784

File tree

13 files changed

+111
-77
lines changed

13 files changed

+111
-77
lines changed

base/boot.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@
9090
#end
9191

9292
#struct LineInfoNode
93-
# mod::Module
94-
# method::Symbol
93+
# method::Any
9594
# file::Symbol
9695
# line::Int
9796
# inlined_at::Int
@@ -375,8 +374,8 @@ eval(Core, :(PiNode(val, typ) = $(Expr(:new, :PiNode, :val, :typ))))
375374
eval(Core, :(PhiCNode(values::Array{Any, 1}) = $(Expr(:new, :PhiCNode, :values))))
376375
eval(Core, :(UpsilonNode(val) = $(Expr(:new, :UpsilonNode, :val))))
377376
eval(Core, :(UpsilonNode() = $(Expr(:new, :UpsilonNode))))
378-
eval(Core, :(LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int) =
379-
$(Expr(:new, :LineInfoNode, :mod, :method, :file, :line, :inlined_at))))
377+
eval(Core, :(LineInfoNode(@nospecialize(method), file::Symbol, line::Int, inlined_at::Int) =
378+
$(Expr(:new, :LineInfoNode, :method, :file, :line, :inlined_at))))
380379

381380
Module(name::Symbol=:anonymous, std_imports::Bool=true) = ccall(:jl_f_new_module, Ref{Module}, (Any, Bool), name, std_imports)
382381

base/compiler/ssair/driver.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

33
using Core: LineInfoNode
4-
const NullLineInfo = LineInfoNode(@__MODULE__, Symbol(""), Symbol(""), 0, 0)
54

65
if false
76
import Base: Base, @show
@@ -103,8 +102,7 @@ function just_construct_ssa(ci::CodeInfo, code::Vector{Any}, nargs::Int, sv::Opt
103102
defuse_insts = scan_slot_def_use(nargs, ci, code)
104103
@timeit "domtree 1" domtree = construct_domtree(cfg)
105104
ir = let code = Any[nothing for _ = 1:length(code)]
106-
argtypes = sv.slottypes[1:(nargs+1)]
107-
IRCode(code, Any[], ci.codelocs, flags, cfg, collect(LineInfoNode, ci.linetable), argtypes, meta, sv.sptypes)
105+
IRCode(code, Any[], ci.codelocs, flags, cfg, collect(LineInfoNode, ci.linetable), sv.slottypes, meta, sv.sptypes)
108106
end
109107
@timeit "construct_ssa" ir = construct_ssa!(ci, code, ir, domtree, defuse_insts, nargs, sv.sptypes, sv.slottypes)
110108
return ir

base/compiler/ssair/inlining.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ end
5656
function ssa_inlining_pass!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::OptimizationState)
5757
# Go through the function, performing simple ininlingin (e.g. replacing call by constants
5858
# and analyzing legality of inlining).
59-
@timeit "analysis" todo = assemble_inline_todo!(ir, linetable, sv)
59+
@timeit "analysis" todo = assemble_inline_todo!(ir, sv)
6060
isempty(todo) && return ir
6161
# Do the actual inlining for every call we identified
6262
@timeit "execution" ir = batch_inline!(todo, ir, linetable, sv)
@@ -289,7 +289,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
289289
# Append the linetable of the inlined function to our line table
290290
inlined_at = Int(compact.result_lines[idx])
291291
for entry in item.linetable
292-
push!(linetable, LineInfoNode(entry.mod, entry.method, entry.file, entry.line,
292+
push!(linetable, LineInfoNode(entry.method, entry.file, entry.line,
293293
(entry.inlined_at > 0 ? entry.inlined_at + linetable_offset : inlined_at)))
294294
end
295295
if item.isva
@@ -702,7 +702,16 @@ function analyze_method!(idx::Int, @nospecialize(f), @nospecialize(ft), @nospeci
702702
end
703703

704704
@timeit "inline IR inflation" begin
705-
ir2, inline_linetable = inflate_ir(src, linfo), src.linetable
705+
ir2 = inflate_ir(src, linfo)
706+
# prepare inlining linetable with method instance information
707+
inline_linetable = Vector{LineInfoNode}(undef, length(src.linetable))
708+
for i = 1:length(src.linetable)
709+
entry = src.linetable[i]
710+
if entry.inlined_at === 0 && entry.method === method
711+
entry = LineInfoNode(linfo, entry.file, entry.line, entry.inlined_at)
712+
end
713+
inline_linetable[i] = entry
714+
end
706715
end
707716
#verify_ir(ir2)
708717

@@ -777,7 +786,7 @@ function handle_single_case!(ir::IRCode, stmt::Expr, idx::Int, @nospecialize(cas
777786
nothing
778787
end
779788

780-
function assemble_inline_todo!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::OptimizationState)
789+
function assemble_inline_todo!(ir::IRCode, sv::OptimizationState)
781790
# todo = (inline_idx, (isva, isinvoke, na), method, spvals, inline_linetable, inline_ir, lie)
782791
todo = Any[]
783792
for idx in 1:length(ir.stmts)

base/compiler/ssair/legacy.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ end
5151
function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
5252
@assert isempty(ir.new_nodes)
5353
# All but the first `nargs` slots will now be unused
54-
resize!(ci.slotnames, nargs+1)
5554
resize!(ci.slotflags, nargs+1)
5655
ci.code = ir.stmts
5756
ci.codelocs = ir.lines

base/compiler/ssair/show.jl

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ function default_expr_type_printer(io::IO, @nospecialize(typ), used::Bool)
153153
nothing
154154
end
155155

156+
normalize_method_name(m::Method) = m.name
157+
normalize_method_name(m::MethodInstance) = (m.def::Method).name
158+
normalize_method_name(m::Symbol) = m
159+
normalize_method_name(m) = Symbol("")
160+
@noinline method_name(m::LineInfoNode) = normalize_method_name(m.method)
161+
156162
# converts the linetable for line numbers
157163
# into a list in the form:
158164
# 1 outer-most-frame
@@ -266,7 +272,7 @@ function compute_ir_line_annotations(code::Union{IRCode, CodeInfo})
266272
# be a line number mismatch in inner most frame. Ignore those
267273
if length(last_stack) == length(stack) && first_mismatch == length(stack)
268274
last_entry, entry = linetable[last_stack[end]], linetable[stack[end]]
269-
if last_entry.method == entry.method && last_entry.file == entry.file
275+
if method_name(last_entry) === method_name(entry) && last_entry.file === entry.file
270276
first_mismatch = nothing
271277
end
272278
end
@@ -299,13 +305,14 @@ function compute_ir_line_annotations(code::Union{IRCode, CodeInfo})
299305
print(buf, "")
300306
end
301307
end
302-
print(buf, ""^max(0,depth-last_depth-stole_one))
308+
print(buf, ""^max(0, depth - last_depth - stole_one))
303309
if printing_depth != 0
304310
if length(stack) == printing_depth
305-
loc_method = String(linetable[line].method)
311+
loc_method = line
306312
else
307-
loc_method = String(linetable[stack[printing_depth+1]].method)
313+
loc_method = stack[printing_depth + 1]
308314
end
315+
loc_method = method_name(linetable[loc_method])
309316
end
310317
loc_method = string(" "^printing_depth, loc_method)
311318
end
@@ -326,14 +333,14 @@ Base.show(io::IO, code::IRCode) = show_ir(io, code)
326333

327334
lineinfo_disabled(io::IO, linestart::String, lineidx::Int32) = ""
328335

329-
function DILineInfoPrinter(linetable::Vector)
336+
function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false)
330337
context = LineInfoNode[]
331338
context_depth = Ref(0)
332339
indent(s::String) = s^(max(context_depth[], 1) - 1)
333340
function emit_lineinfo_update(io::IO, linestart::String, lineidx::Int32)
334341
# internal configuration options:
335342
linecolor = :yellow
336-
collapse = true
343+
collapse = showtypes ? false : true
337344
indent_all = true
338345
# convert lineidx to a vector
339346
if lineidx < 0
@@ -373,11 +380,11 @@ function DILineInfoPrinter(linetable::Vector)
373380
# if so, drop all existing calls to it from the top of the context
374381
# AND check if instead the context was previously printed that way
375382
# but now has removed the recursive frames
376-
let method = context[nctx].method
377-
if (nctx < nframes && DI[nframes - nctx].method === method) ||
378-
(nctx < length(context) && context[nctx + 1].method === method)
383+
let method = method_name(context[nctx])
384+
if (nctx < nframes && method_name(DI[nframes - nctx]) === method) ||
385+
(nctx < length(context) && method_name(context[nctx + 1]) === method)
379386
update_line_only = true
380-
while nctx > 0 && context[nctx].method === method
387+
while nctx > 0 && method_name(context[nctx]) === method
381388
nctx -= 1
382389
end
383390
end
@@ -388,9 +395,9 @@ function DILineInfoPrinter(linetable::Vector)
388395
# compute the new inlining depth
389396
if collapse
390397
npops = 1
391-
let Prev = context[nctx + 1].method
398+
let Prev = method_name(context[nctx + 1])
392399
for i = (nctx + 2):length(context)
393-
Next = context[i].method
400+
Next = method_name(context[i])
394401
Prev === Next || (npops += 1)
395402
Prev = Next
396403
end
@@ -402,9 +409,8 @@ function DILineInfoPrinter(linetable::Vector)
402409
if !update_line_only && nctx < nframes
403410
let CtxLine = context[nctx + 1],
404411
FrameLine = DI[nframes - nctx]
405-
if CtxLine.file == FrameLine.file &&
406-
CtxLine.method == FrameLine.method &&
407-
CtxLine.mod == FrameLine.mod
412+
if CtxLine.file === FrameLine.file &&
413+
method_name(CtxLine) === method_name(FrameLine)
408414
update_line_only = true
409415
end
410416
end
@@ -426,12 +432,12 @@ function DILineInfoPrinter(linetable::Vector)
426432
if frame.line != typemax(frame.line) && frame.line != 0
427433
print(io, linestart)
428434
Base.with_output_color(linecolor, io) do io
429-
print(io, indent(""), " @ ", frame.file, ":", frame.line, " within `", frame.method, "'")
435+
print(io, indent(""), " @ ", frame.file, ":", frame.line, " within `", method_name(frame), "'")
430436
if collapse
431-
method = frame.method
437+
method = method_name(frame)
432438
while nctx < nframes
433439
frame = DI[nframes - nctx]
434-
frame.method === method || break
440+
method_name(frame) === method || break
435441
nctx += 1
436442
push!(context, frame)
437443
print(io, " @ ", frame.file, ":", frame.line)
@@ -444,23 +450,33 @@ function DILineInfoPrinter(linetable::Vector)
444450
# now print the rest of the new frames
445451
while nctx < nframes
446452
frame = DI[nframes - nctx]
453+
nctx += 1
454+
started = false
455+
if showtypes && !isa(frame.method, Symbol) && nctx != 1
456+
print(io, linestart)
457+
Base.with_output_color(linecolor, io) do io
458+
print(io, indent(""))
459+
print(io, "┌ invoke ", frame.method)
460+
println(io)
461+
end
462+
started = true
463+
end
447464
print(io, linestart)
448465
Base.with_output_color(linecolor, io) do io
449466
print(io, indent(""))
450-
nctx += 1
451467
push!(context, frame)
452468
context_depth[] += 1
453-
nctx != 1 && print(io, "")
469+
nctx != 1 && print(io, started ? "" : "")
454470
print(io, " @ ", frame.file)
455471
if frame.line != typemax(frame.line) && frame.line != 0
456472
print(io, ":", frame.line)
457473
end
458-
print(io, " within `", frame.method, "'")
474+
print(io, " within `", method_name(frame), "'")
459475
if collapse
460-
method = frame.method
476+
method = method_name(frame)
461477
while nctx < nframes
462478
frame = DI[nframes - nctx]
463-
frame.method === method || break
479+
method_name(frame) === method || break
464480
nctx += 1
465481
push!(context, frame)
466482
print(io, " @ ", frame.file, ":", frame.line)
@@ -471,10 +487,10 @@ function DILineInfoPrinter(linetable::Vector)
471487
end
472488
# FOR DEBUGGING `collapse`:
473489
# this double-checks the computation of context_depth
474-
#let Prev = context[1].method,
490+
#let Prev = method_name(context[1]),
475491
# depth2 = 1
476492
# for i = 2:nctx
477-
# Next = context[i].method
493+
# Next = method_name(context[i])
478494
# (collapse && Prev === Next) || (depth2 += 1)
479495
# Prev = Next
480496
# end
@@ -565,7 +581,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print
565581
printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black)
566582
print(io, bb_guard_rail)
567583
ssa_guard = " "^(maxlength_idx + 4 + (i - 1))
568-
entry_label = "$(ssa_guard)$(entry.method) at $(entry.file):$(entry.line) "
584+
entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) "
569585
hline = string(""^(start_column-length(entry_label)-length(bb_guard_rail)+max_depth-i), "")
570586
printstyled(io, string(entry_label, hline), "\n"; color=:light_black)
571587
bb_guard_rail = bb_guard_rail_cont

base/compiler/typeinfer.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
const COMPILER_TEMP_SYM = Symbol("#temp#")
4-
53
# build (and start inferring) the inference frame for the linfo
64
function typeinf(result::InferenceResult, cached::Bool, params::Params)
75
frame = InferenceState(result, cached, params)
@@ -123,6 +121,9 @@ function cache_result(result::InferenceResult, min_valid::UInt, max_valid::UInt)
123121
ccall(:jl_isa_compileable_sig, Int32, (Any, Any), result.linfo.specTypes, def) != 0)
124122
if cache_the_tree
125123
# compress code for non-toplevel thunks
124+
nslots = length(inferred_result.slotflags)
125+
resize!(inferred_result.slottypes, nslots)
126+
resize!(inferred_result.slotnames, nslots)
126127
inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), def, inferred_result)
127128
else
128129
inferred_result = nothing
@@ -553,15 +554,15 @@ function typeinf_ext(linfo::MethodInstance, params::Params)
553554
tree.slotflags = fill(0x00, nargs)
554555
tree.ssavaluetypes = 1
555556
tree.codelocs = Int32[1]
556-
tree.linetable = [LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)]
557+
tree.linetable = [LineInfoNode(method, method.file, Int(method.line), 0)]
557558
tree.inferred = true
558559
tree.ssaflags = UInt8[0]
559560
tree.pure = true
560561
tree.inlineable = true
561562
tree.parent = linfo
562563
tree.rettype = typeof(linfo.inferred_const)
563-
tree.min_world = li.min_world
564-
tree.max_world = li.max_world
564+
tree.min_world = linfo.min_world
565+
tree.max_world = linfo.max_world
565566
i == 2 && ccall(:jl_typeinf_end, Cvoid, ())
566567
return svec(linfo, tree)
567568
elseif isa(inf, CodeInfo)

src/ast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *m
554554
else if (sym == thunk_sym) {
555555
ex = scm_to_julia_(fl_ctx, car_(e), mod);
556556
assert(jl_is_code_info(ex));
557-
jl_linenumber_to_lineinfo((jl_code_info_t*)ex, mod, jl_symbol("top-level scope"));
557+
jl_linenumber_to_lineinfo((jl_code_info_t*)ex, (jl_value_t*)jl_symbol("top-level scope"));
558558
temp = (jl_value_t*)jl_exprn(sym, 1);
559559
jl_exprargset(temp, 0, ex);
560560
}

src/codegen.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5355,19 +5355,19 @@ static std::unique_ptr<Module> emit_function(
53555355
if (!JL_FEAT_TEST(ctx, track_allocations))
53565356
malloc_log_mode = JL_LOG_NONE;
53575357

5358-
ctx.file = "<missing>";
53595358
StringRef dbgFuncName = ctx.name;
53605359
int toplineno = -1;
53615360
if (jl_is_method(lam->def.method)) {
53625361
toplineno = lam->def.method->line;
5363-
if (lam->def.method->file != empty_sym)
5364-
ctx.file = jl_symbol_name(lam->def.method->file);
5362+
ctx.file = jl_symbol_name(lam->def.method->file);
53655363
}
53665364
else if (jl_array_len(src->linetable) > 0) {
53675365
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, 0);
5368-
ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
5369-
toplineno = jl_unbox_long(jl_fieldref(locinfo, 3));
5366+
ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 1));
5367+
toplineno = jl_unbox_long(jl_fieldref(locinfo, 2));
53705368
}
5369+
if (ctx.file.empty())
5370+
ctx.file = "<missing>";
53715371
// jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
53725372
// jl_symbol_name(ctx.name), ctx.file.str().c_str(), toplineno);
53735373

@@ -5936,25 +5936,36 @@ static std::unique_ptr<Module> emit_function(
59365936
std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
59375937
linetable.resize(nlocs + 1);
59385938
for (size_t i = 0; i < nlocs; i++) {
5939-
// LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int)
5939+
// LineInfoNode(mod::Module, method::Any, file::Symbol, line::Int, inlined_at::Int)
59405940
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i);
59415941
DebugLineTable &info = linetable[i + 1];
59425942
assert(jl_typeis(locinfo, jl_lineinfonode_type));
5943-
jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0);
5944-
if (module == ctx.module)
5945-
info.is_user_code = mod_is_user_mod;
5946-
else
5947-
info.is_user_code = in_user_mod(module);
5948-
jl_sym_t *method = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1);
5949-
jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2);
5950-
info.line = jl_unbox_long(jl_fieldref(locinfo, 3));
5951-
info.inlined_at = jl_unbox_long(jl_fieldref(locinfo, 4));
5943+
jl_value_t *method = jl_fieldref_noalloc(locinfo, 0);
5944+
if (jl_is_method_instance(method))
5945+
method = ((jl_method_instance_t*)method)->def.value;
5946+
jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1);
5947+
info.line = jl_unbox_long(jl_fieldref(locinfo, 2));
5948+
info.inlined_at = jl_unbox_long(jl_fieldref(locinfo, 3));
59525949
assert(info.inlined_at <= i);
5950+
if (jl_is_method(method)) {
5951+
jl_module_t *module = ((jl_method_t*)method)->module;
5952+
if (module == ctx.module)
5953+
info.is_user_code = mod_is_user_mod;
5954+
else
5955+
info.is_user_code = in_user_mod(module);
5956+
}
5957+
else {
5958+
info.is_user_code = (info.inlined_at == 0) ? mod_is_user_mod : linetable.at(info.inlined_at).is_user_code;
5959+
}
59535960
info.file = jl_symbol_name(filesym);
59545961
if (info.file.empty())
59555962
info.file = "<missing>";
59565963
if (ctx.debug_enabled) {
5957-
StringRef fname = jl_symbol_name(method);
5964+
StringRef fname;
5965+
if (jl_is_method(method))
5966+
method = (jl_value_t*)((jl_method_t*)method)->name;
5967+
if (jl_is_symbol(method))
5968+
fname = jl_symbol_name((jl_sym_t*)method);
59585969
if (fname.empty())
59595970
fname = "macro expansion";
59605971
if (info.inlined_at == 0 && info.file == ctx.file) { // if everything matches, emit a toplevel line number

0 commit comments

Comments
 (0)