From: Xiangdong Ji Date: Thu, 9 Feb 2023 09:31:14 +0000 (+0800) Subject: cmd/compile/internal/pgo: fix RedirectEdges X-Git-Tag: go1.21rc1~1470 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5e4e2acc8e53022f57398c4b0f3892f8113687f6;p=gostls13.git cmd/compile/internal/pgo: fix RedirectEdges 'RedirectEdges' may range over an out-edge slice under modification, leading to out-of-index panic, and reuse an IREdge object by mistake if there are multiple inlining call-sites. Fix by rewriting part of the redirecting operation. Remove 'redirectEdges' as it's not used now and not working as expected in case of multiple inlining call-sites. Fixes #58437. Change-Id: Ic344d4c262df548529acdc9380636cb50835ca51 Reviewed-on: https://go-review.googlesource.com/c/go/+/466915 TryBot-Result: Gopher Robot Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui Reviewed-by: Michael Pratt --- diff --git a/src/cmd/compile/internal/pgo/irgraph.go b/src/cmd/compile/internal/pgo/irgraph.go index 6d957485ce..2185044089 100644 --- a/src/cmd/compile/internal/pgo/irgraph.go +++ b/src/cmd/compile/internal/pgo/irgraph.go @@ -457,37 +457,36 @@ func (p *Profile) PrintWeightedCallGraphDOT(edgeThreshold float64) { func (p *Profile) RedirectEdges(cur *IRNode, inlinedCallSites map[CallSiteInfo]struct{}) { g := p.WeightedCG - for i, outEdge := range g.OutEdges[cur] { - if _, found := inlinedCallSites[CallSiteInfo{LineOffset: outEdge.CallSiteOffset, Caller: cur.AST}]; !found { + i := 0 + outs := g.OutEdges[cur] + for i < len(outs) { + outEdge := outs[i] + redirected := false + _, found := inlinedCallSites[CallSiteInfo{LineOffset: outEdge.CallSiteOffset, Caller: cur.AST}] + if !found { for _, InEdge := range g.InEdges[cur] { if _, ok := inlinedCallSites[CallSiteInfo{LineOffset: InEdge.CallSiteOffset, Caller: InEdge.Src.AST}]; ok { weight := g.calculateWeight(InEdge.Src, cur) - g.redirectEdge(InEdge.Src, cur, outEdge, weight, i) + g.redirectEdge(InEdge.Src, outEdge, weight) + redirected = true } } - } else { + } + if found || redirected { g.remove(cur, i) + outs = g.OutEdges[cur] + continue } + i++ } } -// redirectEdges deletes the cur node out-edges and redirect them so now these -// edges are the parent node out-edges. -func (g *IRGraph) redirectEdges(parent *IRNode, cur *IRNode) { - for _, outEdge := range g.OutEdges[cur] { - outEdge.Src = parent - g.OutEdges[parent] = append(g.OutEdges[parent], outEdge) - } - delete(g.OutEdges, cur) -} - -// redirectEdge deletes the cur-node's out-edges and redirect them so now these -// edges are the parent node out-edges. -func (g *IRGraph) redirectEdge(parent *IRNode, cur *IRNode, outEdge *IREdge, weight int64, idx int) { - outEdge.Src = parent - outEdge.Weight = weight * outEdge.Weight - g.OutEdges[parent] = append(g.OutEdges[parent], outEdge) - g.remove(cur, idx) +// redirectEdge redirects a node's out-edge to one of its parent nodes, cloning is +// required as the node might be inlined in multiple call-sites. +// TODO: adjust the in-edges of outEdge.Dst if necessary +func (g *IRGraph) redirectEdge(parent *IRNode, outEdge *IREdge, weight int64) { + edge := &IREdge{Src: parent, Dst: outEdge.Dst, Weight: weight * outEdge.Weight, CallSiteOffset: outEdge.CallSiteOffset} + g.OutEdges[parent] = append(g.OutEdges[parent], edge) } // remove deletes the cur-node's out-edges at index idx.