-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
Specify interface for LibGit2 abstract types #36452
Conversation
This improves inference results for a number LibGit2 operations, and reduces invalidations from methods (notably, `peel`) that operate on the values extracted from these fields.
13fd24a
to
b609aa4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure why this is necessary to help out inference. The change itself is compatible with all existing LibGit2 AbstractGitObject subtypes
else | ||
return getfield(obj, name) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a comment should be added explaining that this helps inference as on its own the function looks redundant
Good point. This came up in the invalidation hunt after I'd been doing it a while, and I guess I got overly brief. Here's the issue: sometimes, the only thing inference knows is that Specifically, in this case here's what happens: julia/stdlib/LibGit2/src/merge.jl Lines 43 to 47 in 0960c9a
As you might imagine, inference doesn't know the precise type of julia/stdlib/LibGit2/src/repository.jl Lines 254 to 262 in 0960c9a
In detail, julia> code_warntype(LibGit2.peel, (Type{LibGit2.GitCommit}, LibGit2.GitObject))
Variables
#self#::Core.Compiler.Const(LibGit2.peel, false)
#unused#::Core.Compiler.Const(LibGit2.GitCommit, false)
obj::LibGit2.GitObject
new_ptr_ptr::Base.RefValue{Ptr{Nothing}}
err::Int32
Body::LibGit2.GitCommit
1 ─ LibGit2.ensure_initialized()
│ %2 = Core.apply_type(LibGit2.Ptr, LibGit2.Cvoid)::Core.Compiler.Const(Ptr{Nothing}, false)
│ %3 = Core.apply_type(LibGit2.Ref, %2)::Core.Compiler.Const(Ref{Ptr{Nothing}}, false)
│ (new_ptr_ptr = (%3)(LibGit2.C_NULL))
│ %5 = Core.apply_type(LibGit2.Ptr, LibGit2.Cvoid)::Core.Compiler.Const(Ptr{Nothing}, false)
│ %6 = Core.apply_type(LibGit2.Ptr, %5)::Core.Compiler.Const(Ptr{Ptr{Nothing}}, false)
│ %7 = Base.cconvert(%6, new_ptr_ptr)::Base.RefValue{Ptr{Nothing}}
│ %8 = Core.apply_type(LibGit2.Ptr, LibGit2.Cvoid)::Core.Compiler.Const(Ptr{Nothing}, false)
│ %9 = Base.getproperty(obj, :ptr)::Any
│ %10 = Base.cconvert(%8, %9)::Any
│ %11 = LibGit2.Consts.OBJECT::Core.Compiler.Const(LibGit2.Consts.OBJECT, false)
│ %12 = (%11)($(Expr(:static_parameter, 1)))::Core.Compiler.Const(LibGit2.Consts.OBJ_COMMIT, false)
│ %13 = Base.cconvert(LibGit2.Cint, %12)::Core.Compiler.Const(1, false)
│ %14 = Core.apply_type(LibGit2.Ptr, LibGit2.Cvoid)::Core.Compiler.Const(Ptr{Nothing}, false)
│ %15 = Core.apply_type(LibGit2.Ptr, %14)::Core.Compiler.Const(Ptr{Ptr{Nothing}}, false)
│ %16 = Base.unsafe_convert(%15, %7)::Ptr{Ptr{Nothing}}
│ %17 = Core.apply_type(LibGit2.Ptr, LibGit2.Cvoid)::Core.Compiler.Const(Ptr{Nothing}, false)
│ %18 = Base.unsafe_convert(%17, %10)::Any
│ %19 = Base.unsafe_convert(LibGit2.Cint, %13)::Core.Compiler.Const(1, false)
│ %20 = $(Expr(:foreigncall, (:git_object_peel, :libgit2), Int32, svec(Ptr{Ptr{Nothing}}, Ptr{Nothing}, Int32), 0, :(:ccall), :(%16), :(%18), :(%19), :(%13), :(%10), :(%7)))::Int32
│ (err = LibGit2.Cint(%20))
│ %22 = (err < 0)::Bool
└── goto #3 if not %22
2 ─ %24 = LibGit2.Error.GitError::Core.Compiler.Const(LibGit2.Error.GitError, false)
│ %25 = (%24)(err)::LibGit2.Error.GitError
└── LibGit2.throw(%25)
3 ┄ err
│ %28 = Base.getproperty(obj, :owner)::Any
│ %29 = Base.getindex(new_ptr_ptr)::Ptr{Nothing}
│ %30 = ($(Expr(:static_parameter, 1)))(%28, %29)::LibGit2.GitCommit
└── return %30 You can see that the call (line 9) Why is that a problem? Because StaticArrays defines this method: https://github.com/JuliaArrays/StaticArrays.jl/blob/f972d162dc3a8810d2a188feda2a737201fe8790/src/FieldArray.jl#L123 (which it's well within its rights to do). Julia notices that this method would, if applicable, supersede We can fix that if inference knows that Does that answer your question 😄? Perhaps the length of this explanation excuses some of my brevity at the beginning, but I should have said more. What fraction of this would you like in a comment? Or we could just add a comment referring to this PR? |
Codecov Report
@@ Coverage Diff @@
## master #36452 +/- ##
==========================================
+ Coverage 86.12% 86.16% +0.03%
==========================================
Files 349 349
Lines 65408 65659 +251
==========================================
+ Hits 56335 56574 +239
- Misses 9073 9085 +12
Continue to review full report at Codecov.
|
@timholy that definitely answers my question. If you just a comment mentioning the |
This improves inference results for a number LibGit2 operations, and reduces invalidations from methods (notably, `peel`) that operate on the values extracted from these fields.
This improves inference results for a number LibGit2 operations, and reduces invalidations from methods (notably,
peel
) that operate on the values extracted from these fields.