// Copyright 2017 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gocore

import (
	"sort"

	"golang.org/x/debug/internal/core"
)

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 })
	})
}

// ForEachReversePtr calls fn for all pointers it finds pointing to y.
// It calls fn with:
//   the object or root which points to y (exactly one will be non-nil)
//   the offset i in that object or root where the pointer appears.
//   the offset j in y where the pointer points.
// If fn returns false, ForEachReversePtr returns immediately.
func (p *Process) ForEachReversePtr(y Object, fn func(x Object, r *Root, i, j int64) bool) {
	p.reverseEdges()

	idx, _ := p.findObjectIndex(p.Addr(y))
	for _, a := range p.redge[p.ridx[idx]:p.ridx[idx+1]] {
		// Read pointer, compute offset in y.
		ptr := p.proc.ReadPtr(a)
		j := ptr.Sub(p.Addr(y))

		// Find source of pointer.
		x, i := p.FindObject(a)
		if x != 0 {
			// Source is an object.
			if !fn(x, nil, i, j) {
				return
			}
			continue
		}
		// Source is a root.
		k := sort.Search(len(p.rootIdx), func(k int) bool {
			r := p.rootIdx[k]
			return a < r.Addr.Add(r.Type.Size)
		})
		r := p.rootIdx[k]
		if !fn(0, r, a.Sub(r.Addr), j) {
			return
		}
	}
}

func (p *Process) findRootIndex(r *Root) int {
	return sort.Search(len(p.rootIdx), func(k int) bool {
		return p.rootIdx[k].Addr >= r.Addr
	})
}
