Skip to content

Commit

Permalink
Merge pull request #31015 from JuliaLang/jn/codeinfo-plus
Browse files Browse the repository at this point in the history
store additional "unnecessary" information in CodeInfo
  • Loading branch information
vtjnash committed Feb 16, 2019
2 parents f9c7716 + 42b6571 commit 68db871
Show file tree
Hide file tree
Showing 34 changed files with 449 additions and 324 deletions.
7 changes: 3 additions & 4 deletions base/boot.jl
Expand Up @@ -90,8 +90,7 @@
#end

#struct LineInfoNode
# mod::Module
# method::Symbol
# method::Any
# file::Symbol
# line::Int
# inlined_at::Int
Expand Down Expand Up @@ -375,8 +374,8 @@ eval(Core, :(PiNode(val, typ) = $(Expr(:new, :PiNode, :val, :typ))))
eval(Core, :(PhiCNode(values::Array{Any, 1}) = $(Expr(:new, :PhiCNode, :values))))
eval(Core, :(UpsilonNode(val) = $(Expr(:new, :UpsilonNode, :val))))
eval(Core, :(UpsilonNode() = $(Expr(:new, :UpsilonNode))))
eval(Core, :(LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int) =
$(Expr(:new, :LineInfoNode, :mod, :method, :file, :line, :inlined_at))))
eval(Core, :(LineInfoNode(@nospecialize(method), file::Symbol, line::Int, inlined_at::Int) =
$(Expr(:new, :LineInfoNode, :method, :file, :line, :inlined_at))))

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

Expand Down
4 changes: 2 additions & 2 deletions base/compiler/inferencestate.jl
Expand Up @@ -58,7 +58,7 @@ mutable struct InferenceState
s_types = Any[ nothing for i = 1:n ]

# initial types
nslots = length(src.slotnames)
nslots = length(src.slotflags)
argtypes = result.argtypes
nargs = length(argtypes)
s_argtypes = VarTable(undef, nslots)
Expand Down Expand Up @@ -122,7 +122,7 @@ end

function sptypes_from_meth_instance(linfo::MethodInstance)
toplevel = !isa(linfo.def, Method)
if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms)
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
# linfo is unspecialized
sp = Any[]
sig = linfo.def.sig
Expand Down
9 changes: 6 additions & 3 deletions base/compiler/optimize.jl
Expand Up @@ -37,8 +37,11 @@ mutable struct OptimizationState
if nssavalues isa Int
src.ssavaluetypes = Any[ Any for i = 1:nssavalues ]
end
nslots = length(src.slotnames)
slottypes = Any[ Any for i = 1:nslots ]
nslots = length(src.slotflags)
slottypes = src.slottypes
if slottypes === nothing
slottypes = Any[ Any for i = 1:nslots ]
end
s_edges = []
# cache some useful state computations
toplevel = !isa(linfo.def, Method)
Expand Down Expand Up @@ -73,7 +76,7 @@ end
# This is implied by `SLOT_USEDUNDEF`.
# If this is not set, all the uses are (statically) dominated by the defs.
# In particular, if a slot has `AssignedOnce && !StaticUndef`, it is an SSA.
const SLOT_STATICUNDEF = 1
const SLOT_STATICUNDEF = 1 # slot might be used before it is defined (structurally)
const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once
const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
# const SLOT_CALLED = 64
Expand Down
4 changes: 1 addition & 3 deletions base/compiler/ssair/driver.jl
@@ -1,7 +1,6 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Core: LineInfoNode
const NullLineInfo = LineInfoNode(@__MODULE__, Symbol(""), Symbol(""), 0, 0)

if false
import Base: Base, @show
Expand Down Expand Up @@ -103,8 +102,7 @@ function just_construct_ssa(ci::CodeInfo, code::Vector{Any}, nargs::Int, sv::Opt
defuse_insts = scan_slot_def_use(nargs, ci, code)
@timeit "domtree 1" domtree = construct_domtree(cfg)
ir = let code = Any[nothing for _ = 1:length(code)]
argtypes = sv.slottypes[1:(nargs+1)]
IRCode(code, Any[], ci.codelocs, flags, cfg, collect(LineInfoNode, ci.linetable), argtypes, meta, sv.sptypes)
IRCode(code, Any[], ci.codelocs, flags, cfg, collect(LineInfoNode, ci.linetable), sv.slottypes, meta, sv.sptypes)
end
@timeit "construct_ssa" ir = construct_ssa!(ci, code, ir, domtree, defuse_insts, nargs, sv.sptypes, sv.slottypes)
return ir
Expand Down
17 changes: 13 additions & 4 deletions base/compiler/ssair/inlining.jl
Expand Up @@ -56,7 +56,7 @@ end
function ssa_inlining_pass!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::OptimizationState)
# Go through the function, performing simple ininlingin (e.g. replacing call by constants
# and analyzing legality of inlining).
@timeit "analysis" todo = assemble_inline_todo!(ir, linetable, sv)
@timeit "analysis" todo = assemble_inline_todo!(ir, sv)
isempty(todo) && return ir
# Do the actual inlining for every call we identified
@timeit "execution" ir = batch_inline!(todo, ir, linetable, sv)
Expand Down Expand Up @@ -289,7 +289,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
# Append the linetable of the inlined function to our line table
inlined_at = Int(compact.result_lines[idx])
for entry in item.linetable
push!(linetable, LineInfoNode(entry.mod, entry.method, entry.file, entry.line,
push!(linetable, LineInfoNode(entry.method, entry.file, entry.line,
(entry.inlined_at > 0 ? entry.inlined_at + linetable_offset : inlined_at)))
end
if item.isva
Expand Down Expand Up @@ -702,7 +702,16 @@ function analyze_method!(idx::Int, @nospecialize(f), @nospecialize(ft), @nospeci
end

@timeit "inline IR inflation" begin
ir2, inline_linetable = inflate_ir(src, linfo), src.linetable
ir2 = inflate_ir(src, linfo)
# prepare inlining linetable with method instance information
inline_linetable = Vector{LineInfoNode}(undef, length(src.linetable))
for i = 1:length(src.linetable)
entry = src.linetable[i]
if entry.inlined_at === 0 && entry.method === method
entry = LineInfoNode(linfo, entry.file, entry.line, entry.inlined_at)
end
inline_linetable[i] = entry
end
end
#verify_ir(ir2)

Expand Down Expand Up @@ -777,7 +786,7 @@ function handle_single_case!(ir::IRCode, stmt::Expr, idx::Int, @nospecialize(cas
nothing
end

function assemble_inline_todo!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::OptimizationState)
function assemble_inline_todo!(ir::IRCode, sv::OptimizationState)
# todo = (inline_idx, (isva, isinvoke, na), method, spvals, inline_linetable, inline_ir, lie)
todo = Any[]
for idx in 1:length(ir.stmts)
Expand Down
8 changes: 4 additions & 4 deletions base/compiler/ssair/legacy.jl
@@ -1,13 +1,11 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotnames) ])

function inflate_ir(ci::CodeInfo, linfo::MethodInstance)
sptypes = sptypes_from_meth_instance(linfo)
if ci.inferred
argtypes, _ = matching_cache_argtypes(linfo, nothing)
else
argtypes = Any[ Any for i = 1:length(ci.slotnames) ]
argtypes = Any[ Any for i = 1:length(ci.slotflags) ]
end
return inflate_ir(ci, sptypes, argtypes)
end
Expand Down Expand Up @@ -53,7 +51,6 @@ end
function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
@assert isempty(ir.new_nodes)
# All but the first `nargs` slots will now be unused
resize!(ci.slotnames, nargs+1)
resize!(ci.slotflags, nargs+1)
ci.code = ir.stmts
ci.codelocs = ir.lines
Expand Down Expand Up @@ -92,3 +89,6 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
end
end
end

# used by some tests
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotflags) ])
68 changes: 42 additions & 26 deletions base/compiler/ssair/show.jl
Expand Up @@ -153,6 +153,12 @@ function default_expr_type_printer(io::IO, @nospecialize(typ), used::Bool)
nothing
end

normalize_method_name(m::Method) = m.name
normalize_method_name(m::MethodInstance) = (m.def::Method).name
normalize_method_name(m::Symbol) = m
normalize_method_name(m) = Symbol("")
@noinline method_name(m::LineInfoNode) = normalize_method_name(m.method)

# converts the linetable for line numbers
# into a list in the form:
# 1 outer-most-frame
Expand Down Expand Up @@ -266,7 +272,7 @@ function compute_ir_line_annotations(code::Union{IRCode, CodeInfo})
# be a line number mismatch in inner most frame. Ignore those
if length(last_stack) == length(stack) && first_mismatch == length(stack)
last_entry, entry = linetable[last_stack[end]], linetable[stack[end]]
if last_entry.method == entry.method && last_entry.file == entry.file
if method_name(last_entry) === method_name(entry) && last_entry.file === entry.file
first_mismatch = nothing
end
end
Expand Down Expand Up @@ -299,13 +305,14 @@ function compute_ir_line_annotations(code::Union{IRCode, CodeInfo})
print(buf, "")
end
end
print(buf, ""^max(0,depth-last_depth-stole_one))
print(buf, ""^max(0, depth - last_depth - stole_one))
if printing_depth != 0
if length(stack) == printing_depth
loc_method = String(linetable[line].method)
loc_method = line
else
loc_method = String(linetable[stack[printing_depth+1]].method)
loc_method = stack[printing_depth + 1]
end
loc_method = method_name(linetable[loc_method])
end
loc_method = string(" "^printing_depth, loc_method)
end
Expand All @@ -326,14 +333,14 @@ Base.show(io::IO, code::IRCode) = show_ir(io, code)

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

function DILineInfoPrinter(linetable::Vector)
function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false)
context = LineInfoNode[]
context_depth = Ref(0)
indent(s::String) = s^(max(context_depth[], 1) - 1)
function emit_lineinfo_update(io::IO, linestart::String, lineidx::Int32)
# internal configuration options:
linecolor = :yellow
collapse = true
collapse = showtypes ? false : true
indent_all = true
# convert lineidx to a vector
if lineidx < 0
Expand Down Expand Up @@ -373,11 +380,11 @@ function DILineInfoPrinter(linetable::Vector)
# if so, drop all existing calls to it from the top of the context
# AND check if instead the context was previously printed that way
# but now has removed the recursive frames
let method = context[nctx].method
if (nctx < nframes && DI[nframes - nctx].method === method) ||
(nctx < length(context) && context[nctx + 1].method === method)
let method = method_name(context[nctx])
if (nctx < nframes && method_name(DI[nframes - nctx]) === method) ||
(nctx < length(context) && method_name(context[nctx + 1]) === method)
update_line_only = true
while nctx > 0 && context[nctx].method === method
while nctx > 0 && method_name(context[nctx]) === method
nctx -= 1
end
end
Expand All @@ -388,9 +395,9 @@ function DILineInfoPrinter(linetable::Vector)
# compute the new inlining depth
if collapse
npops = 1
let Prev = context[nctx + 1].method
let Prev = method_name(context[nctx + 1])
for i = (nctx + 2):length(context)
Next = context[i].method
Next = method_name(context[i])
Prev === Next || (npops += 1)
Prev = Next
end
Expand All @@ -402,9 +409,8 @@ function DILineInfoPrinter(linetable::Vector)
if !update_line_only && nctx < nframes
let CtxLine = context[nctx + 1],
FrameLine = DI[nframes - nctx]
if CtxLine.file == FrameLine.file &&
CtxLine.method == FrameLine.method &&
CtxLine.mod == FrameLine.mod
if CtxLine.file === FrameLine.file &&
method_name(CtxLine) === method_name(FrameLine)
update_line_only = true
end
end
Expand All @@ -426,12 +432,12 @@ function DILineInfoPrinter(linetable::Vector)
if frame.line != typemax(frame.line) && frame.line != 0
print(io, linestart)
Base.with_output_color(linecolor, io) do io
print(io, indent(""), " @ ", frame.file, ":", frame.line, " within `", frame.method, "'")
print(io, indent(""), " @ ", frame.file, ":", frame.line, " within `", method_name(frame), "'")
if collapse
method = frame.method
method = method_name(frame)
while nctx < nframes
frame = DI[nframes - nctx]
frame.method === method || break
method_name(frame) === method || break
nctx += 1
push!(context, frame)
print(io, " @ ", frame.file, ":", frame.line)
Expand All @@ -444,23 +450,33 @@ function DILineInfoPrinter(linetable::Vector)
# now print the rest of the new frames
while nctx < nframes
frame = DI[nframes - nctx]
nctx += 1
started = false
if showtypes && !isa(frame.method, Symbol) && nctx != 1
print(io, linestart)
Base.with_output_color(linecolor, io) do io
print(io, indent(""))
print(io, "┌ invoke ", frame.method)
println(io)
end
started = true
end
print(io, linestart)
Base.with_output_color(linecolor, io) do io
print(io, indent(""))
nctx += 1
push!(context, frame)
context_depth[] += 1
nctx != 1 && print(io, "")
nctx != 1 && print(io, started ? "" : "")
print(io, " @ ", frame.file)
if frame.line != typemax(frame.line) && frame.line != 0
print(io, ":", frame.line)
end
print(io, " within `", frame.method, "'")
print(io, " within `", method_name(frame), "'")
if collapse
method = frame.method
method = method_name(frame)
while nctx < nframes
frame = DI[nframes - nctx]
frame.method === method || break
method_name(frame) === method || break
nctx += 1
push!(context, frame)
print(io, " @ ", frame.file, ":", frame.line)
Expand All @@ -471,10 +487,10 @@ function DILineInfoPrinter(linetable::Vector)
end
# FOR DEBUGGING `collapse`:
# this double-checks the computation of context_depth
#let Prev = context[1].method,
#let Prev = method_name(context[1]),
# depth2 = 1
# for i = 2:nctx
# Next = context[i].method
# Next = method_name(context[i])
# (collapse && Prev === Next) || (depth2 += 1)
# Prev = Next
# end
Expand Down Expand Up @@ -565,7 +581,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print
printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black)
print(io, bb_guard_rail)
ssa_guard = " "^(maxlength_idx + 4 + (i - 1))
entry_label = "$(ssa_guard)$(entry.method) at $(entry.file):$(entry.line) "
entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) "
hline = string(""^(start_column-length(entry_label)-length(bb_guard_rail)+max_depth-i), "")
printstyled(io, string(entry_label, hline), "\n"; color=:light_black)
bb_guard_rail = bb_guard_rail_cont
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/ssair/slot2ssa.jl
Expand Up @@ -45,7 +45,7 @@ end

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

0 comments on commit 68db871

Please sign in to comment.