|
1 | 1 | # MethodAnalysis.jl
|
2 | 2 |
|
3 |
| -```@index |
| 3 | +This package facilitates introspection of Julia's internals, with a particular focus on its MethodInstances and their backedges. |
| 4 | + |
| 5 | +!!! warning |
| 6 | + Julia's internals are not subject to the same stability guarantee that the rest of the language enjoys. |
| 7 | + |
| 8 | +## Demonstrations |
| 9 | + |
| 10 | +A few demonstrations will give you a taste of what can be done with this package. |
| 11 | + |
| 12 | +### Collecting all submodules of Base |
| 13 | + |
| 14 | +```jldoctest |
| 15 | +julia> using MethodAnalysis |
| 16 | +
|
| 17 | +julia> mods = Module[]; |
| 18 | +
|
| 19 | +julia> visit(Base; print=false) do obj |
| 20 | + if isa(obj, Module) |
| 21 | + push!(mods, obj) |
| 22 | + end |
| 23 | + end |
| 24 | +
|
| 25 | +julia> Base.FastMath ∈ mods |
| 26 | +true |
| 27 | +``` |
| 28 | + |
| 29 | +### Collecting all Methods in Core.Compiler |
| 30 | + |
| 31 | +`visit` also descends into functions, methods, and MethodInstances: |
| 32 | + |
| 33 | +```jldoctest; setup=:(using MethodAnalysis) |
| 34 | +julia> meths = [] |
| 35 | +Any[] |
| 36 | +
|
| 37 | +julia> visit(Core.Compiler) do item # without print=false it will display the modules it visits |
| 38 | + isa(item, Method) && push!(meths, item) |
| 39 | + end |
| 40 | +Module Core.Compiler |
| 41 | +Module Core.Compiler.CoreDocs |
| 42 | +Module Core.Compiler.Iterators |
| 43 | +Module Core.Compiler.Order |
| 44 | +Module Core.Compiler.Sort |
| 45 | +Module Core.Compiler.Sort.Float |
| 46 | +
|
| 47 | +julia> first(methods(Core.Compiler.typeinf_ext)) ∈ meths |
| 48 | +true |
| 49 | +``` |
| 50 | + |
| 51 | +### Getting a MethodInstance for a particular set of types |
| 52 | + |
| 53 | +```jldoctest; setup=:(using MethodAnalysis) |
| 54 | +julia> foo(::AbstractVector) = 1 |
| 55 | +foo (generic function with 1 method) |
| 56 | +
|
| 57 | +julia> instance(foo, (Vector{Int},)) # we haven't called it yet, so it's not compiled |
| 58 | +
|
| 59 | +julia> foo([1,2]) |
| 60 | +1 |
| 61 | +
|
| 62 | +julia> instance(foo, (Vector{Int},)) |
| 63 | +MethodInstance for foo(::Array{Int64,1}) |
| 64 | +``` |
| 65 | + |
| 66 | +### Collecting a subset of MethodInstances for a particular function |
| 67 | + |
| 68 | +Let's collect all single-argument compiled instances of `findfirst`: |
| 69 | + |
| 70 | +```jldoctest findfirst; setup=:(using MethodAnalysis) |
| 71 | +julia> mis = Core.MethodInstance[]; |
| 72 | +
|
| 73 | +julia> visit(findfirst) do item |
| 74 | + isa(item, Core.MethodInstance) && length(Base.unwrap_unionall(item.specTypes).parameters) == 2 && push!(mis, item) |
| 75 | + end |
| 76 | +
|
| 77 | +julia> mis |
| 78 | +1-element Array{Core.MethodInstance,1}: |
| 79 | + MethodInstance for findfirst(::BitArray{1}) |
| 80 | +``` |
| 81 | + |
| 82 | +We checked that the length was 2, rather than 1, because the first parameter is the function type itself: |
| 83 | + |
| 84 | +```jldoctest findfirst |
| 85 | +julia> mis[1].specTypes |
| 86 | +Tuple{typeof(findfirst),BitArray{1}} |
4 | 87 | ```
|
5 | 88 |
|
6 |
| -```@autodocs |
7 |
| -Modules = [MethodAnalysis] |
| 89 | +### Getting the backedges for a function |
| 90 | + |
| 91 | +Let's see all the compiled instances of `Base.setdiff` and their immediate callers: |
| 92 | + |
| 93 | +```jldoctest; setup=(using MethodAnalysis) |
| 94 | +julia> direct_backedges(setdiff) |
| 95 | +3-element Array{Any,1}: |
| 96 | + MethodInstance for setdiff(::Base.KeySet{Any,Dict{Any,Any}}, ::Base.KeySet{Any,Dict{Any,Any}}) => MethodInstance for keymap_merge(::Dict{Char,Any}, ::Dict{Any,Any}) |
| 97 | + MethodInstance for setdiff(::Base.KeySet{Any,Dict{Any,Any}}, ::Base.KeySet{Any,Dict{Any,Any}}) => MethodInstance for keymap_merge(::Any, ::Dict{Any,Any}) |
| 98 | + MethodInstance for setdiff(::Array{Base.UUID,1}, ::Array{Base.UUID,1}) => MethodInstance for deps_graph(::Pkg.Types.Context, ::Dict{Base.UUID,String}, ::Dict{Base.UUID,Pkg.Types.VersionSpec}, ::Dict{Base.UUID,Pkg.Resolve.Fixed}) |
| 99 | +``` |
| 100 | + |
| 101 | +### Printing backedges as a tree |
| 102 | + |
| 103 | +MethodAnalysis uses [AbstractTrees](https://github.com/JuliaCollections/AbstractTrees.jl) to display the complete set of backedges: |
| 104 | + |
| 105 | +```jldoctest; setup=:(using MethodAnalysis) |
| 106 | +julia> mi = instance(findfirst, (BitVector,)) |
| 107 | +MethodInstance for findfirst(::BitArray{1}) |
| 108 | +
|
| 109 | +julia> MethodAnalysis.print_tree(mi) |
| 110 | +MethodInstance for findfirst(::BitArray{1}) |
| 111 | +├─ MethodInstance for prune_graph!(::Graph) |
| 112 | +│ └─ MethodInstance for #simplify_graph!#111(::Bool, ::typeof(simplify_graph!), ::Graph, ::Set{Int64}) |
| 113 | +│ └─ MethodInstance for simplify_graph!(::Graph, ::Set{Int64}) |
| 114 | +│ └─ MethodInstance for simplify_graph!(::Graph) |
| 115 | +│ ├─ MethodInstance for trigger_failure!(::Graph, ::Array{Int64,1}, ::Tuple{Int64,Int64}) |
| 116 | +│ │ ⋮ |
| 117 | +│ │ |
| 118 | +│ └─ MethodInstance for resolve_versions!(::Context, ::Array{PackageSpec,1}) |
| 119 | +│ ⋮ |
| 120 | +│ |
| 121 | +└─ MethodInstance for update_solution!(::SolutionTrace, ::Graph) |
| 122 | + └─ MethodInstance for converge!(::Graph, ::Messages, ::SolutionTrace, ::NodePerm, ::MaxSumParams) |
| 123 | + ├─ MethodInstance for converge!(::Graph, ::Messages, ::SolutionTrace, ::NodePerm, ::MaxSumParams) |
| 124 | + │ ├─ MethodInstance for converge!(::Graph, ::Messages, ::SolutionTrace, ::NodePerm, ::MaxSumParams) |
| 125 | + │ │ ├─ MethodInstance for converge!(::Graph, ::Messages, ::SolutionTrace, ::NodePerm, ::MaxSumParams) |
| 126 | + │ │ │ ⋮ |
| 127 | + │ │ │ |
| 128 | + │ │ └─ MethodInstance for maxsum(::Graph) |
| 129 | + │ │ ⋮ |
| 130 | + │ │ |
| 131 | + │ └─ MethodInstance for maxsum(::Graph) |
| 132 | + │ └─ MethodInstance for resolve(::Graph) |
| 133 | + │ ⋮ |
| 134 | + │ |
| 135 | + └─ MethodInstance for maxsum(::Graph) |
| 136 | + └─ MethodInstance for resolve(::Graph) |
| 137 | + ├─ MethodInstance for trigger_failure!(::Graph, ::Array{Int64,1}, ::Tuple{Int64,Int64}) |
| 138 | + │ ⋮ |
| 139 | + │ |
| 140 | + └─ MethodInstance for resolve_versions!(::Context, ::Array{PackageSpec,1}) |
| 141 | + ⋮ |
| 142 | +``` |
| 143 | + |
| 144 | +## API reference |
| 145 | + |
| 146 | +### visit |
| 147 | + |
| 148 | +```@docs |
| 149 | +visit |
| 150 | +visit_backedges |
| 151 | +``` |
| 152 | + |
| 153 | +### backedges |
| 154 | + |
| 155 | +```@docs |
| 156 | +all_backedges |
| 157 | +direct_backedges |
| 158 | +terminal_backedges |
| 159 | +with_all_backedges |
| 160 | +``` |
| 161 | + |
| 162 | +### utilities |
| 163 | + |
| 164 | +```@docs |
| 165 | +instance |
| 166 | +call_type |
| 167 | +worlds |
8 | 168 | ```
|
0 commit comments