Skip to content

Commit 9675acc

Browse files
authored
Merge pull request #8 from timholy/teh/more_demos
More demos
2 parents 30b1ee7 + f396fee commit 9675acc

File tree

3 files changed

+540
-0
lines changed

3 files changed

+540
-0
lines changed

demos/abstract_analyze_versions.jl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using PyPlot
2+
3+
function parseline(line)
4+
m = match(r"(.*) => (.*)", line)
5+
sigstr, count = m.captures[1], parse(Int, m.captures[2])
6+
sig = try
7+
ex = Meta.parse(sigstr)
8+
eval(ex)
9+
catch
10+
return nothing
11+
end
12+
return sig, count
13+
end
14+
15+
function parsedata(filename)
16+
lines = readlines(filename)
17+
sigcount = IdDict{Any,Int}()
18+
for line in lines
19+
ret = parseline(line)
20+
ret === nothing && continue
21+
sig, count = ret
22+
sigcount[sig] = count
23+
end
24+
return sigcount
25+
end
26+
27+
function split_comparable(sigc1, sigc2)
28+
c1, c2, sigs = Int[], Int[], Any[]
29+
for (sig, c) in sigc1
30+
push!(sigs, sig)
31+
push!(c1, sigc1[sig])
32+
push!(c2, get(sigc2, sig, 0))
33+
end
34+
for (sig, c) in sigc2
35+
if !haskey(sigc1, sig)
36+
push!(sigs, sig)
37+
push!(c1, 0)
38+
push!(c2, c)
39+
end
40+
end
41+
return sigs, c1, c2
42+
end
43+
44+
sigc16 = parsedata("/tmp/methdata_$VERSION.log")
45+
sigc14 = parsedata("/tmp/methdata_1.4.3-pre.0.log")
46+
47+
sigs, c1, c2 = split_comparable(sigc14, sigc16)
48+
mx1, mx2 = maximum(c1), maximum(c2)
49+
isexported(sig) = (ft = Base.unwrap_unionall(sig).parameters[1]; isdefined(Main, ft.name.mt.name))
50+
colors = [isexported(sig) ? "magenta" : "green" for sig in sigs]
51+
52+
function on_click(event)
53+
x, y = event.xdata, event.ydata
54+
normsqrdist(pr) = ((pr[1]-x)/mx1)^2 + ((pr[2]-y)/mx2)^2
55+
idx = argmin(normsqrdist.(zip(c1, c2)))
56+
println(sigs[idx])
57+
end
58+
begin
59+
fig, ax = plt.subplots()
60+
ax.scatter(c1 .+ 1, c2 .+ 1, c=colors) # + 1 for the log-scaling
61+
ax.set_xlabel("# backedges + 1, 1.4")
62+
ax.set_ylabel("# backedges + 1, 1.6")
63+
ax.set_xscale("log")
64+
ax.set_yscale("log")
65+
fig.canvas.callbacks.connect("button_press_event", on_click)
66+
fig
67+
end
68+
69+
# Ones we've made progress on:
70+
# ==(::Any, Symbol)
71+
# ==(::Symbol, ::Any)
72+
# ==(::Any, ::Nothing)
73+
# ==(::UUID, ::Any)
74+
# ==(::AbstractString, ::String)
75+
# isequal(::Symbol, ::Any)
76+
# isequal(::Any, ::Symbol)
77+
# isequal(::Any, ::Nothing)
78+
# isequal(::UUID, ::Any)
79+
# cmp(::AbstractString, ::String)
80+
# convert(::Type{Int}, ::Integer)
81+
# convert(::Type{UInt}, ::Integer)
82+
# convert(::Type{Union{Nothing,Module}}, ::Any)
83+
# Base.to_index(::Integer)
84+
# iterate(::Base.OneTo, ::Any)
85+
# repr(::Any)
86+
# thisind(::AbstractString, ::Int)
87+
# getindex(::String, ::Any)
88+
# string(::String, ::Integer, ::String)
89+
# ^(::String, ::Integer)
90+
# repeat(::String, ::Integer)
91+
# Base.isidentifier(::AbstractString)
92+
# +(::Ptr{UInt8}, ::Integer)
93+
# Base._show_default(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Any)
94+
95+
# Ones that are better but I don't remember helping with
96+
# isconcretetype(::Any)
97+
# pointer(::String, ::Integer)
98+
99+
# Regressions:
100+
# basename(::AbstractString)
101+
# splitdir(::AbstractString)
102+
# isfile(::Any)
103+
# joinpath(::AbstractString, ::String)
104+
# sizeof(::Unsigned)
105+
# +(::Int, ::Any, ::Any)
106+
# Base.split_sign(::Integer)
107+
# in(::Any, ::Tuple{Symbol})

demos/abstract_gen_data.jl

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using MethodAnalysis
2+
3+
# Analyze MethodInstance signatures and select those that seem at risk for being invalidated.
4+
function atrisktype(@nospecialize(typ))
5+
# signatures like `convert(Vector, a)`, `foo(::Vararg{Synbol,N}) where N` do not seem to pose a problem
6+
isa(typ, TypeVar) && return false
7+
# isbits parameters are not a problem
8+
isa(typ, Type) || return false
9+
if isa(typ, UnionAll)
10+
typ = Base.unwrap_unionall(typ)
11+
end
12+
# Exclude signatures with Union{}
13+
typ === Union{} && return false
14+
isa(typ, Union) && return atrisktype(typ.a) | atrisktype(typ.b)
15+
# Type{T}: signatures like `convert(::Type{AbstractString}, ::String)` are not problematic, so mark Type as OK
16+
typ <: Type && return false
17+
if typ <: Tuple && length(typ.parameters) >= 1
18+
p1 = typ.parameters[1]
19+
# Constructor calls are not themselves a problem (any `convert`s they trigger might be, but those are covered)
20+
isa(p1, Type) && p1 <: Type && return false
21+
# convert(::Type{T}, ::S) where S<:T is not problematic
22+
if p1 === typeof(Base.convert) || p1 === typeof(Core.convert) || p1 === typeof(Core.Compiler.convert)
23+
p2, p3 = typ.parameters[2], typ.parameters[3]
24+
if isa(p2, Type)
25+
p2 = Base.unwrap_unionall(p2)
26+
if isa(p2, DataType) && length(p2.parameters) === 1
27+
T = p2.parameters[1]
28+
isa(p3, Type) && isa(T, Type) && p3 <: T && return false
29+
end
30+
end
31+
# `getindex`, `length`, etc are OK for various Tuple{T1,T2,...}
32+
elseif (p1 === typeof(Base.getindex) || p1 === typeof(Core.Compiler.getindex)) ||
33+
(p1 === typeof(Base.length) || p1 === typeof(Core.Compiler.length)) ||
34+
(p1 === typeof(Base.isempty) || p1 === typeof(Core.Compiler.isempty)) ||
35+
(p1 === typeof(Base.iterate) || p1 === typeof(Core.iterate) || p1 === typeof(Core.Compiler.iterate))
36+
p2 = typ.parameters[2]
37+
if isa(p2, Type)
38+
p2 = Base.unwrap_unionall(p2)
39+
p2 <: Tuple && return false
40+
end
41+
# show(io::IO, x) is OK as long as typeof(x) is safe
42+
elseif p1 === typeof(Base.show)
43+
atrisktype(typ.parameters[2]) && return true
44+
length(typ.parameters) == 3 && atrisktype(typ.parameters[3]) && return true
45+
return false
46+
end
47+
end
48+
# Standard DataTypes
49+
isconcretetype(typ) && return false
50+
# ::Function args are excluded
51+
typ === Function && return false
52+
!isempty(typ.parameters) && (any(atrisktype, typ.parameters) || return false)
53+
return true
54+
end
55+
56+
# A few tests
57+
@assert atrisktype(Tuple{typeof(==),Any,Any})
58+
@assert atrisktype(Tuple{typeof(==),Symbol,Any})
59+
@assert atrisktype(Tuple{typeof(==),Any,Symbol})
60+
@assert !atrisktype(Tuple{typeof(==),Symbol,Symbol})
61+
@assert !atrisktype(Tuple{typeof(convert),Type{Any},Any})
62+
@assert !atrisktype(Tuple{typeof(convert),Type{AbstractString},AbstractString})
63+
@assert !atrisktype(Tuple{typeof(convert),Type{AbstractString},String})
64+
@assert atrisktype(Tuple{typeof(convert),Type{String},AbstractString})
65+
@assert !atrisktype(Tuple{typeof(map),Function,Vector{Any}})
66+
@assert !atrisktype(Tuple{typeof(getindex),Dict{Union{String,Int},Any},Union{String,Int}})
67+
@assert atrisktype(Tuple{typeof(getindex),Dict{Union{String,Int},Any},Any})
68+
@assert !atrisktype(Tuple{Type{BoundsError},Any,Any})
69+
@assert atrisktype(Tuple{typeof(sin),Any})
70+
@assert !atrisktype(Tuple{typeof(length),Tuple{Any,Any}})
71+
72+
function collect_mis(m::Method)
73+
list = Core.MethodInstance[]
74+
visit(m) do item
75+
if isa(item, Core.MethodInstance)
76+
push!(list, item)
77+
return false
78+
end
79+
return true
80+
end
81+
return list
82+
end
83+
84+
const mis = Dict{Method,Vector{Core.MethodInstance}}()
85+
visit() do item
86+
if item isa Method
87+
m = item
88+
mis[m] = collect_mis(m)
89+
return false
90+
end
91+
return true
92+
end
93+
94+
# Count # of backedges for MethodInstances with abstract types
95+
const becounter = Dict{Core.MethodInstance,Int}()
96+
visit() do item
97+
if item isa Core.MethodInstance
98+
if atrisktype(item.specTypes)
99+
becounter[item] = length(all_backedges(item))
100+
end
101+
return false
102+
end
103+
return true
104+
end
105+
106+
prs = sort!(collect(becounter); by=last)
107+
108+
# Organize them by method instead
109+
110+
const mcounter = Dict{Method,Int}()
111+
for (mi, c) in becounter
112+
oc = get(mcounter, mi.def, 0)
113+
mcounter[mi.def] = oc + c
114+
end
115+
116+
mprs = sort!(collect(mcounter); by=last)
117+
118+
open("/tmp/methinstdata_$VERSION.log", "w") do io
119+
for (mi, c) in prs
120+
c == 0 && continue
121+
println(io, mi.specTypes=>c)
122+
end
123+
end
124+
open("/tmp/methdata_$VERSION.log", "w") do io
125+
for (m, c) in mprs
126+
c == 0 && continue
127+
println(io, m.sig=>c)
128+
end
129+
end

0 commit comments

Comments
 (0)