in internal/gocore/reverse.go [13:79]
func (p *Process) reverseEdges() {
p.initReverseEdges.Do(func() {
// First, count the number of edges into each object.
// This allows for efficient packing of the reverse edge storage.
cnt := make([]int64, p.nObj+1)
p.ForEachObject(func(x Object) bool {
p.ForEachPtr(x, func(_ int64, y Object, _ int64) bool {
idx, _ := p.findObjectIndex(p.Addr(y))
cnt[idx]++
return true
})
return true
})
p.ForEachRoot(func(r *Root) bool {
p.ForEachRootPtr(r, func(_ int64, y Object, _ int64) bool {
idx, _ := p.findObjectIndex(p.Addr(y))
cnt[idx]++
return true
})
return true
})
// Compute cumulative count of all incoming edges up to and including each object.
var n int64
for idx, c := range cnt {
n += c
cnt[idx] = n
}
// Allocate all the storage for the reverse edges.
p.redge = make([]core.Address, n)
// Add edges to the lists.
p.ForEachObject(func(x Object) bool {
p.ForEachPtr(x, func(i int64, y Object, _ int64) bool {
idx, _ := p.findObjectIndex(p.Addr(y))
e := cnt[idx]
e--
cnt[idx] = e
p.redge[e] = p.Addr(x).Add(i)
return true
})
return true
})
p.ForEachRoot(func(r *Root) bool {
p.ForEachRootPtr(r, func(i int64, y Object, _ int64) bool {
idx, _ := p.findObjectIndex(p.Addr(y))
e := cnt[idx]
e--
cnt[idx] = e
p.redge[e] = r.Addr.Add(i)
return true
})
return true
})
// At this point, cnt contains the cumulative count of all edges up to
// but *not* including each object.
p.ridx = cnt
// Make root index.
p.ForEachRoot(func(r *Root) bool {
p.rootIdx = append(p.rootIdx, r)
return true
})
sort.Slice(p.rootIdx, func(i, j int) bool { return p.rootIdx[i].Addr < p.rootIdx[j].Addr })
})
}