Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some nospecialization hacks #43087

Merged
merged 1 commit into from
Nov 15, 2021
Merged

add some nospecialization hacks #43087

merged 1 commit into from
Nov 15, 2021

Conversation

aviatesk
Copy link
Sponsor Member

@aviatesk aviatesk commented Nov 15, 2021

The previous @nospecialize(::Type) dispatch signatures actually disabled
nospecializations, and we see following kind of dynamic dispatches:

julia> using JET

julia> report_opt((Vector{Any},)) do ts
           isbitstype(ts[1])
       end
═════ 1 possible error found ═════
┌ @ REPL[3]:2 Main.isbitstype(%1)
│ runtime dispatch detected: Main.isbitstype(%1::Any)
└─────────────

This commit also adds an overload of emptymutable(::IdSet), which
eliminates the dynamic dispatch below:

julia> report_opt((Base.IdSet{Any}, Base.IdSet{Any}); annotate_types=true) do s1, s2
           s1  s2
       end
═════ 2 possible errors found ═════
┌ @ REPL[3]:2 Main.∪(s1::Base.IdSet{Any}, s2::Base.IdSet{Any})
│┌ @ abstractset.jl:48 Base.union!(Core.tuple(Base.emptymutable(s::Base.IdSet{Any}, Base.promote_eltype(Core.tuple(s::Base.IdSet{Any})::Tuple{Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)::Type{Any})::Set{Any}, s::B>
││┌ @ abstractset.jl:76 Base.union!(s::Set{Any}, x::Base.IdSet{Any})
│││┌ @ abstractset.jl:93 Base.sizehint!(s::Set{Any}, Base.+(Base.length(s::Set{Any})::Int64, Core.typeassert(Base.Int(Base.length(itr::Base.IdSet{Any})::Int64)::Int64, Base.Int)::Int64)::Int64)
││││┌ @ set.jl:84 Base.sizehint!(Base.getproperty(s::Set{Any}, :dict::Symbol)::Dict{Any, Nothing}, newsz::Int64)
│││││┌ @ dict.jl:244 Base.rehash!(d::Dict{Any, Nothing}, newsz::Int64)
││││││┌ @ dict.jl:203 Base.hashindex(%231::Any, %20::Int64)
│││││││ runtime dispatch detected: Base.hashindex(%231::Any, %20::Int64)
││││││└───────────────
│││┌ @ abstractset.jl:95 Base.push!(s::Set{Any}, %62::Any)
││││ runtime dispatch detected: Base.push!(s::Set{Any}, %62::Any)
│││└─────────────────────

The previous `@nospecialize(::Type)` dispatch signatures actually disabled
nospecializations, and we see following kind of dynamic dispatches:
```julia
julia> using JET

julia> report_opt((Vector{Any},)) do ts
           isbitstype(ts[1])
       end
═════ 1 possible error found ═════
┌ @ REPL[3]:2 Main.isbitstype(%1)
│ runtime dispatch detected: Main.isbitstype(%1::Any)
└─────────────
```

This commit also adds an overload of `emptymutable(::IdSet)`, which
eliminates the dynamic dispatch below:
```julia
julia> report_opt((Base.IdSet{Any}, Base.IdSet{Any}); annotate_types=true) do s1, s2
           s1 ∪ s2
       end
═════ 2 possible errors found ═════
┌ @ REPL[3]:2 Main.∪(s1::Base.IdSet{Any}, s2::Base.IdSet{Any})
│┌ @ abstractset.jl:48 Base.union!(Core.tuple(Base.emptymutable(s::Base.IdSet{Any}, Base.promote_eltype(Core.tuple(s::Base.IdSet{Any})::Tuple{Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)::Type{Any})::Set{Any}, s::Base.IdSet{Any})::Tuple{Set{Any}, Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)
││┌ @ abstractset.jl:76 Base.union!(s::Set{Any}, x::Base.IdSet{Any})
│││┌ @ abstractset.jl:93 Base.sizehint!(s::Set{Any}, Base.+(Base.length(s::Set{Any})::Int64, Core.typeassert(Base.Int(Base.length(itr::Base.IdSet{Any})::Int64)::Int64, Base.Int)::Int64)::Int64)
││││┌ @ set.jl:84 Base.sizehint!(Base.getproperty(s::Set{Any}, :dict::Symbol)::Dict{Any, Nothing}, newsz::Int64)
│││││┌ @ dict.jl:244 Base.rehash!(d::Dict{Any, Nothing}, newsz::Int64)
││││││┌ @ dict.jl:203 Base.hashindex(%231::Any, %20::Int64)
│││││││ runtime dispatch detected: Base.hashindex(%231::Any, %20::Int64)
││││││└───────────────
│││┌ @ abstractset.jl:95 Base.push!(s::Set{Any}, %62::Any)
││││ runtime dispatch detected: Base.push!(s::Set{Any}, %62::Any)
│││└─────────────────────
```
@vtjnash
Copy link
Sponsor Member

vtjnash commented Nov 15, 2021

It doesn't cause any sort of specialization, though it did inhibit inlining:

julia> mt = typeof(isbitstype).name.mt;

julia> mt.leafcache
Any[]

julia> mt.cache
Core.TypeMapEntry(nothing, Tuple{typeof(isbitstype), Type}, Tuple{typeof(isbitstype), Any}, svec(), 0x00000000000012d4, 0xffffffffffffffff, MethodInstance for isbitstype(::Type), false, false, false)

@aviatesk
Copy link
Sponsor Member Author

So does that mean the runtime avoids specialization when a dispatch signature contains Type as an heuristic?
I thought a dynamic dispatch usually causes a specialization.

aviatesk added a commit that referenced this pull request Nov 16, 2021
aviatesk added a commit that referenced this pull request Nov 20, 2021
LilithHafner pushed a commit to LilithHafner/julia that referenced this pull request Feb 22, 2022
The previous `@nospecialize(::Type)` dispatch signatures actually caused the following kinds of dynamic dispatches:
```julia
julia> using JET

julia> report_opt((Vector{Any},)) do ts
           isbitstype(ts[1])
       end
═════ 1 possible error found ═════
┌ @ REPL[3]:2 Main.isbitstype(%1)
│ runtime dispatch detected: Main.isbitstype(%1::Any)
└─────────────
```

This commit also adds an overload of `emptymutable(::IdSet)`, which
eliminates the dynamic dispatch below:
```julia
julia> report_opt((Base.IdSet{Any}, Base.IdSet{Any}); annotate_types=true) do s1, s2
           s1 ∪ s2
       end
═════ 2 possible errors found ═════
┌ @ REPL[3]:2 Main.∪(s1::Base.IdSet{Any}, s2::Base.IdSet{Any})
│┌ @ abstractset.jl:48 Base.union!(Core.tuple(Base.emptymutable(s::Base.IdSet{Any}, Base.promote_eltype(Core.tuple(s::Base.IdSet{Any})::Tuple{Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)::Type{Any})::Set{Any}, s::Base.IdSet{Any})::Tuple{Set{Any}, Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)
││┌ @ abstractset.jl:76 Base.union!(s::Set{Any}, x::Base.IdSet{Any})
│││┌ @ abstractset.jl:93 Base.sizehint!(s::Set{Any}, Base.+(Base.length(s::Set{Any})::Int64, Core.typeassert(Base.Int(Base.length(itr::Base.IdSet{Any})::Int64)::Int64, Base.Int)::Int64)::Int64)
││││┌ @ set.jl:84 Base.sizehint!(Base.getproperty(s::Set{Any}, :dict::Symbol)::Dict{Any, Nothing}, newsz::Int64)
│││││┌ @ dict.jl:244 Base.rehash!(d::Dict{Any, Nothing}, newsz::Int64)
││││││┌ @ dict.jl:203 Base.hashindex(%231::Any, %20::Int64)
│││││││ runtime dispatch detected: Base.hashindex(%231::Any, %20::Int64)
││││││└───────────────
│││┌ @ abstractset.jl:95 Base.push!(s::Set{Any}, %62::Any)
││││ runtime dispatch detected: Base.push!(s::Set{Any}, %62::Any)
│││└─────────────────────
```
LilithHafner pushed a commit to LilithHafner/julia that referenced this pull request Mar 8, 2022
The previous `@nospecialize(::Type)` dispatch signatures actually caused the following kinds of dynamic dispatches:
```julia
julia> using JET

julia> report_opt((Vector{Any},)) do ts
           isbitstype(ts[1])
       end
═════ 1 possible error found ═════
┌ @ REPL[3]:2 Main.isbitstype(%1)
│ runtime dispatch detected: Main.isbitstype(%1::Any)
└─────────────
```

This commit also adds an overload of `emptymutable(::IdSet)`, which
eliminates the dynamic dispatch below:
```julia
julia> report_opt((Base.IdSet{Any}, Base.IdSet{Any}); annotate_types=true) do s1, s2
           s1 ∪ s2
       end
═════ 2 possible errors found ═════
┌ @ REPL[3]:2 Main.∪(s1::Base.IdSet{Any}, s2::Base.IdSet{Any})
│┌ @ abstractset.jl:48 Base.union!(Core.tuple(Base.emptymutable(s::Base.IdSet{Any}, Base.promote_eltype(Core.tuple(s::Base.IdSet{Any})::Tuple{Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)::Type{Any})::Set{Any}, s::Base.IdSet{Any})::Tuple{Set{Any}, Base.IdSet{Any}}, sets::Tuple{Base.IdSet{Any}}...)
││┌ @ abstractset.jl:76 Base.union!(s::Set{Any}, x::Base.IdSet{Any})
│││┌ @ abstractset.jl:93 Base.sizehint!(s::Set{Any}, Base.+(Base.length(s::Set{Any})::Int64, Core.typeassert(Base.Int(Base.length(itr::Base.IdSet{Any})::Int64)::Int64, Base.Int)::Int64)::Int64)
││││┌ @ set.jl:84 Base.sizehint!(Base.getproperty(s::Set{Any}, :dict::Symbol)::Dict{Any, Nothing}, newsz::Int64)
│││││┌ @ dict.jl:244 Base.rehash!(d::Dict{Any, Nothing}, newsz::Int64)
││││││┌ @ dict.jl:203 Base.hashindex(%231::Any, %20::Int64)
│││││││ runtime dispatch detected: Base.hashindex(%231::Any, %20::Int64)
││││││└───────────────
│││┌ @ abstractset.jl:95 Base.push!(s::Set{Any}, %62::Any)
││││ runtime dispatch detected: Base.push!(s::Set{Any}, %62::Any)
│││└─────────────────────
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants