]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile/internal/pgo: fix RedirectEdges
authorXiangdong Ji <jixiangdong@bytedance.com>
Thu, 9 Feb 2023 09:31:14 +0000 (17:31 +0800)
committerWayne Zuo <wdvxdr@golangcn.org>
Mon, 27 Feb 2023 14:40:29 +0000 (14:40 +0000)
'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 <gobot@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/cmd/compile/internal/pgo/irgraph.go

index 6d957485cebbf7689e9c9dc8b7ce094e9a8f727d..21850440896027841f84730c1da3e727151ca874 100644 (file)
@@ -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.