@@ -687,12 +687,17 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter, cycleid::
687687 nothing
688688end
689689
690- # record the backedges
691- function store_backedges (caller:: CodeInstance , edges:: SimpleVector )
692- isa (caller. def. def, Method) || return # don't add backedges to toplevel method instance
693- i = 1
694- while true
695- i > length (edges) && return nothing
690+ # Iterate a series of back-edges that need registering, based on the provided forward edge list.
691+ # Back-edges are returned as (invokesig, item), where the item is a Binding, MethodInstance, or
692+ # MethodTable.
693+ struct ForwardToBackedgeIterator
694+ forward_edges:: SimpleVector
695+ end
696+
697+ function Base. iterate (it:: ForwardToBackedgeIterator , i:: Int = 1 )
698+ edges = it. forward_edges
699+ i > length (edges) && return nothing
700+ while i ≤ length (edges)
696701 item = edges[i]
697702 if item isa Int
698703 i += 2
@@ -702,34 +707,55 @@ function store_backedges(caller::CodeInstance, edges::SimpleVector)
702707 i += 1
703708 continue
704709 elseif isa (item, Core. Binding)
705- i += 1
706- maybe_add_binding_backedge! (item, caller)
707- continue
710+ return ((nothing , item), i + 1 )
708711 end
709712 if isa (item, CodeInstance)
710- item = item. def
711- end
712- if isa (item, MethodInstance) # regular dispatch
713- ccall (:jl_method_instance_add_backedge , Cvoid, (Any, Any, Any), item, nothing , caller)
714- i += 1
713+ item = get_ci_mi (item)
714+ return ((nothing , item), i + 1 )
715+ elseif isa (item, MethodInstance) # regular dispatch
716+ return ((nothing , item), i + 1 )
715717 else
718+ invokesig = item
716719 callee = edges[i+ 1 ]
717- if isa (callee, MethodTable) # abstract dispatch (legacy style edges)
718- ccall (:jl_method_table_add_backedge , Cvoid, (Any, Any, Any), callee, item, caller)
719- i += 2
720- continue
721- elseif isa (callee, Method)
722- # ignore `Method`-edges (from e.g. failed `abstract_call_method`)
723- i += 2
724- continue
725- # `invoke` edge
726- elseif isa (callee, CodeInstance)
727- callee = get_ci_mi (callee)
720+ isa (callee, Method) && (i += 2 ; continue ) # ignore `Method`-edges (from e.g. failed `abstract_call_method`)
721+ if isa (callee, MethodTable)
722+ # abstract dispatch (legacy style edges)
723+ return ((invokesig, callee), i + 2 )
728724 else
729- callee = callee:: MethodInstance
725+ # `invoke` edge
726+ callee = isa (callee, CodeInstance) ? get_ci_mi (callee) : callee:: MethodInstance
727+ return ((invokesig, callee), i + 2 )
728+ end
729+ end
730+ end
731+ return nothing
732+ end
733+
734+ # record the backedges
735+ function store_backedges (caller:: CodeInstance , edges:: SimpleVector )
736+ isa (caller. def. def, Method) || return # don't add backedges to toplevel method instance
737+
738+ backedges = ForwardToBackedgeIterator (edges)
739+ for (i, (invokesig, item)) in enumerate (backedges)
740+ # check for any duplicate edges we've already registered
741+ duplicate_found = false
742+ for (i′, (invokesig′, item′)) in enumerate (backedges)
743+ i == i′ && break
744+ if item′ === item && invokesig′ == invokesig
745+ duplicate_found = true
746+ break
747+ end
748+ end
749+
750+ if ! duplicate_found
751+ if item isa Core. Binding
752+ maybe_add_binding_backedge! (item, caller)
753+ elseif item isa MethodTable
754+ ccall (:jl_method_table_add_backedge , Cvoid, (Any, Any, Any), item, invokesig, caller)
755+ else
756+ item:: MethodInstance
757+ ccall (:jl_method_instance_add_backedge , Cvoid, (Any, Any, Any), item, invokesig, caller)
730758 end
731- ccall (:jl_method_instance_add_backedge , Cvoid, (Any, Any, Any), callee, item, caller)
732- i += 2
733759 end
734760 end
735761 nothing
0 commit comments