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

make delete_method work #6

Merged
merged 1 commit into from
Oct 27, 2019
Merged

make delete_method work #6

merged 1 commit into from
Oct 27, 2019

Conversation

oxinabox
Copy link
Owner

Closes #1

@NHDaly might review

@oxinabox oxinabox merged commit 1695b6c into master Oct 27, 2019
@NHDaly
Copy link
Collaborator

NHDaly commented Oct 27, 2019

Sorry i didn't review this earlier, but this surprises me!

Why does having edges to all the methods fix method deletions? Is it just because you're also adding a method to the method table?

I would assume that whatever mechanism normally handles method deletions should apply in this situation as well, no?

@NHDaly
Copy link
Collaborator

NHDaly commented Oct 27, 2019

For example, here, there's only a single back-edge from f(x::Int) to b, and so then deleting that method invalidates b and causes it to recompile the next time it's called:

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.2.0 (2019-08-20)
 _/ |\__'_|_|_|\__'_|  |
|__/                   |

julia> f(x) = "Any"
f (generic function with 1 method)

julia> b(x) = f(x)
b (generic function with 1 method)

julia> b(1)
"Any"

julia> NHDalyUtils.func_all_backedges(f)
Dict{Any,Array{Any,1}} with 2 entries:
  (f(x) in Main at REPL[1]:1, Tuple{typeof(f),Int64}) => Any[MethodInstance for b(::Int64)]
  :MethodTable                                        => Any[]

julia> f(x::Int) = "int"
f (generic function with 2 methods)

julia> b(1)
"int"

julia> NHDalyUtils.func_all_backedges(f)
Dict{Any,Array{Any,1}} with 3 entries:
  (f(x::Int64) in Main at REPL[5]:1, Tuple{typeof(f),Int64}) => Any[MethodInstance for b(::Int64)]
  (f(x) in Main at REPL[1]:1, Tuple{typeof(f),Int64})        => Any[]
  :MethodTable                                               => Any[]

julia> methods(f).ms
[1] f(x::Int64) in Main at REPL[5]:1
[2] f(x) in Main at REPL[1]:1

julia> Base.delete_method(methods(f).ms[1])

julia> b(1)
"Any"

julia> NHDalyUtils.func_all_backedges(f)
Dict{Any,Array{Any,1}} with 2 entries:
  (f(x) in Main at REPL[1]:1, Tuple{typeof(f),Int64}) => Any[MethodInstance for b(::Int64)]
  :MethodTable                                        => Any[]

julia>

(Where NHDalyUtils comes from here -- sorry it's not a proper package: https://github.com/NHDaly/nhdaly_dotfiles/blob/master/julia/utils.jl)

@oxinabox
Copy link
Owner Author

oxinabox commented Oct 27, 2019

all the methods

Oh that was a bit excessive. yeah.
It was meant to be all the MethodInstances of this method.
Kinda overkill to get all of them.
Technically works though

Needs a follow up to cut them down to just the ones that match this.

I would assume that whatever mechanism normally handles method deletions should apply in this situation as well, no?

I assume I am hooking into whatever mechanism normally handles method deletions.
We need edges between the Method (or well actually MethodIInstances)
so it knows that when the method is deleted,
it needs to recompile static_hasmethod (and thus recompile anything with an edge onto that.)

We can't directly use that mechanism without manually hooking because this is a generated function.

@NHDaly
Copy link
Collaborator

NHDaly commented Oct 27, 2019

gottttcha, you were trying to hit all the method instances 👍

It's kinda dumb, but this is what i've done in the past to get all the specializations:

julia> let
           out = []
           s = m.specializations
           while s isa Core.TypeMapEntry
               push!(out, s)
               s=s.next
           end
           out
       end
1-element Array{Any,1}:
 Core.TypeMapEntry(nothing, Tuple{typeof(f),Int64}, nothing, svec(), 1, -1, MethodInstance for f(::Int64), true, true, false)

@NHDaly
Copy link
Collaborator

NHDaly commented Oct 27, 2019

Oh that was a bit excessive. yeah.
It was meant to be all the MethodInstances of this method.
Kinda overkill to get all of them.
Technically works though

Okay, yeah, it might actually be doing exactly that:

       method_insts = Core.Compiler.method_instances(f.instance, T, world)

One thing to note, though, I think method_instances will create specializations, even if they don't yet exist. I'm not sure if that's a bad thing, necessarily -- it might totally fine in this case, but worth mentioning (and maybe commenting in the code?):

julia> f(x) = "Any"
f (generic function with 1 method)

julia> NHDalyUtils.func_all_backedges(f)
Dict{Symbol,Array{Any,1}} with 1 entry:
  :MethodTable => Any[]

julia> method_insts = Core.Compiler.method_instances(f, (String,), typemax(UInt))
1-element Array{Core.MethodInstance,1}:
 MethodInstance for f(::String)

julia> method_insts = Core.Compiler.method_instances(f, (Any,), typemax(UInt))
1-element Array{Core.MethodInstance,1}:
 MethodInstance for f(::Any)

julia> NHDalyUtils.func_all_backedges(f)
Dict{Any,Array{Any,1}} with 3 entries:
  (f(x) in Main at REPL[41]:1, Tuple{typeof(f),Any})    => Any[]
  (f(x) in Main at REPL[41]:1, Tuple{typeof(f),String}) => Any[]
  :MethodTable                                          => Any[]

@oxinabox
Copy link
Owner Author

How do I go from that Core.TypeMapEntry to a MethodInstance ?

Lyndon White
Is it possible to go from a Core.TypeMapEntry to a MethodInstance ?
Jameson
This is like saying, “is is possible to go from an Array index to a String”

@NHDaly
Copy link
Collaborator

NHDaly commented Oct 28, 2019

Huh, that's surprising. I guess he means that it depends on the context? I'm not sure. Maybe i'm missing something, but I think it's just there in the .func field:

julia> m = methods(f).ms[1]
f(x) in Main at REPL[1]:1

julia> specializations = let
           out = []
           s = m.specializations
           while s isa Core.TypeMapEntry
               push!(out, s)
               s=s.next
           end
           out
       end
1-element Array{Any,1}:
 Core.TypeMapEntry(nothing, Tuple{typeof(f),Int64}, nothing, svec(), 1, -1, MethodInstance for f(::Int64), true, true, false)

julia> mis = [s.func for s in specializations]
1-element Array{Core.MethodInstance,1}:
 MethodInstance for f(::Int64)

julia> mis == Core.Compiler.method_instances(f, (Int,))
true

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.

Make work with delete_method
2 participants