Skip to content

Commit 68db871

Browse files
authored
Merge pull request #31015 from JuliaLang/jn/codeinfo-plus
store additional "unnecessary" information in CodeInfo
2 parents f9c7716 + 42b6571 commit 68db871

34 files changed

+449
-324
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/inferencestate.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mutable struct InferenceState
5858
s_types = Any[ nothing for i = 1:n ]
5959

6060
# initial types
61-
nslots = length(src.slotnames)
61+
nslots = length(src.slotflags)
6262
argtypes = result.argtypes
6363
nargs = length(argtypes)
6464
s_argtypes = VarTable(undef, nslots)
@@ -122,7 +122,7 @@ end
122122

123123
function sptypes_from_meth_instance(linfo::MethodInstance)
124124
toplevel = !isa(linfo.def, Method)
125-
if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms)
125+
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
126126
# linfo is unspecialized
127127
sp = Any[]
128128
sig = linfo.def.sig

base/compiler/optimize.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ mutable struct OptimizationState
3737
if nssavalues isa Int
3838
src.ssavaluetypes = Any[ Any for i = 1:nssavalues ]
3939
end
40-
nslots = length(src.slotnames)
41-
slottypes = Any[ Any for i = 1:nslots ]
40+
nslots = length(src.slotflags)
41+
slottypes = src.slottypes
42+
if slottypes === nothing
43+
slottypes = Any[ Any for i = 1:nslots ]
44+
end
4245
s_edges = []
4346
# cache some useful state computations
4447
toplevel = !isa(linfo.def, Method)
@@ -73,7 +76,7 @@ end
7376
# This is implied by `SLOT_USEDUNDEF`.
7477
# If this is not set, all the uses are (statically) dominated by the defs.
7578
# In particular, if a slot has `AssignedOnce && !StaticUndef`, it is an SSA.
76-
const SLOT_STATICUNDEF = 1
79+
const SLOT_STATICUNDEF = 1 # slot might be used before it is defined (structurally)
7780
const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once
7881
const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
7982
# const SLOT_CALLED = 64

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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotnames) ])
4-
53
function inflate_ir(ci::CodeInfo, linfo::MethodInstance)
64
sptypes = sptypes_from_meth_instance(linfo)
75
if ci.inferred
86
argtypes, _ = matching_cache_argtypes(linfo, nothing)
97
else
10-
argtypes = Any[ Any for i = 1:length(ci.slotnames) ]
8+
argtypes = Any[ Any for i = 1:length(ci.slotflags) ]
119
end
1210
return inflate_ir(ci, sptypes, argtypes)
1311
end
@@ -53,7 +51,6 @@ end
5351
function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
5452
@assert isempty(ir.new_nodes)
5553
# All but the first `nargs` slots will now be unused
56-
resize!(ci.slotnames, nargs+1)
5754
resize!(ci.slotflags, nargs+1)
5855
ci.code = ir.stmts
5956
ci.codelocs = ir.lines
@@ -92,3 +89,6 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
9289
end
9390
end
9491
end
92+
93+
# used by some tests
94+
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotflags) ])

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/ssair/slot2ssa.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ end
4545

4646
@inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id
4747
function scan_slot_def_use(nargs::Int, ci::CodeInfo, code::Vector{Any})
48-
nslots = length(ci.slotnames)
48+
nslots = length(ci.slotflags)
4949
result = SlotInfo[SlotInfo() for i = 1:nslots]
5050
# Set defs for arguments
5151
for var in result[1:(1+nargs)]
@@ -654,7 +654,7 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
654654
undef_token
655655
else
656656
SSAValue(-1)
657-
end for x in 1:length(ci.slotnames)
657+
end for x in 1:length(ci.slotflags)
658658
]
659659
worklist = Tuple{Int, Int, Vector{Any}}[(1, 0, initial_incoming_vals)]
660660
visited = BitSet()

0 commit comments

Comments
 (0)