Last active
November 20, 2019 11:50
-
-
Save timholy/1d0823269a1ceb592bfad457a41f178a to your computer and use it in GitHub Desktop.
Traversing all compiled methods
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function traverse(val, mod::Module, visiting=Set{Module}()) | |
push!(visiting, mod) | |
val = increment(val, mod) | |
for nm in names(mod; all=true) | |
if isdefined(mod, nm) | |
obj = getfield(mod, nm) | |
if isa(obj, Module) | |
obj in visiting && continue | |
val = traverse(val, obj, visiting) | |
else | |
val = traverse(val, obj) | |
end | |
end | |
end | |
return val | |
end | |
function traverse(val, f::Function) | |
val = increment(val, f) | |
Base.visit(methods(f).mt) do m | |
val = traverse(val, m) | |
end | |
return val | |
end | |
function traverse(val, m::Method) | |
val = increment(val, m) | |
for fn in (:specializations, :invokes) | |
if isdefined(m, fn) | |
spec = getfield(m, fn) | |
if spec === nothing | |
elseif isa(spec, Core.TypeMapEntry) || isa(spec, Core.TypeMapLevel) | |
Base.visit(spec) do m | |
val = traverse(val, m) | |
end | |
else | |
error("unhandled type ", typeof(spec)) | |
end | |
end | |
end | |
return val | |
end | |
function traverse(val, mi::Core.MethodInstance) | |
val = increment(val, mi) | |
if isdefined(mi, :cache) | |
val = traverse(val, mi.cache) | |
end | |
return val | |
end | |
function traverse(val, ci::Core.CodeInstance) | |
val = increment(val, ci) | |
inf = ci.inferred | |
if isa(inf, Core.CodeInfo) | |
val = traverse(val, inf) | |
elseif isa(inf, Vector{UInt8}) | |
inf = Core.Compiler._uncompressed_ast(ci, inf) | |
val = traverse(val, inf) | |
elseif isa(inf, Nothing) | |
else | |
error("unhandled type ", typeof(inf)) | |
end | |
return val | |
end | |
traverse(val, x) = increment(val, x) | |
mutable struct TypeCounter{T} | |
nmodules::Int | |
nfunctions::Int | |
nmethods::Int | |
nmethodinstances::Int | |
ncodeinstances::Int | |
ncodeinfos::Int | |
nT::Int | |
end | |
TypeCounter{T}() where T = TypeCounter{T}(0, 0, 0, 0, 0, 0, 0) | |
function increment(val::TypeCounter, ::Module) | |
val.nmodules += 1 | |
return val | |
end | |
function increment(val::TypeCounter, @nospecialize(::Function)) | |
val.nfunctions += 1 | |
return val | |
end | |
function increment(val::TypeCounter, ::Method) | |
val.nmethods += 1 | |
return val | |
end | |
function increment(val::TypeCounter, ::Core.MethodInstance) | |
val.nmethodinstances += 1 | |
return val | |
end | |
function increment(val::TypeCounter, ::Core.CodeInstance) | |
val.ncodeinstances += 1 | |
return val | |
end | |
function increment(val::TypeCounter, src::Core.CodeInfo) | |
val.ncodeinfos += 1 | |
vt = src.ssavaluetypes | |
if isa(vt, Vector{Any}) | |
for typ in vt | |
# performance hotspot, use manual dispatch | |
if isa(typ, TypeVar) | |
val = _increment(val, typ) | |
elseif isa(typ, Core.TypeofBottom) | |
elseif isa(typ, Union) | |
val = _increment(val, typ) | |
elseif isa(typ, UnionAll) | |
val = _increment(val, Base.unwrap_unionall(typ)) | |
elseif isa(typ, DataType) | |
val = _increment(val, typ) | |
end | |
end | |
end | |
return val | |
end | |
function _increment(val::TypeCounter{T}, @nospecialize(typ::Type)) where T | |
typ = Base.unwrap_unionall(typ) | |
typ === Union{} && return val | |
if isa(typ, DataType) | |
if typ <: T | |
val.nT += 1 | |
end | |
for p in typ.parameters | |
if isa(p, Type) | |
val = _increment(val, p) | |
end | |
end | |
elseif isa(typ, Union) | |
val = _increment(val, typ.a) | |
val = _increment(val, typ.b) | |
else | |
error("unhandled type ", typeof(typ)) | |
end | |
return val | |
end | |
function _increment(val::TypeCounter, tv::TypeVar) | |
val = _increment(val, tv.lb) | |
val = _increment(val, tv.ub) | |
end | |
increment(val::TypeCounter, @nospecialize(::Type)) = val | |
increment(val::TypeCounter, ::Any) = val |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment