func (p *Process) Size(x Object) int64 {
	return p.heapInfo[uint64(core.Address(x).Sub(p.arenaStart))/512].size
}
Size returns the size of x in bytes.
package gocore
import (
	"math/bits"
	"strings"
	"github.com/randall77/corelib/core"
)
func (p *Process) readObjects() {
	ptrSize := p.proc.PtrSize()
	n := 0
	var live int64
	var q []Object
	add := func(x core.Address) {
		if x == 0 || x < p.arenaStart || x >= p.arenaUsed {  
			return
		}
		i := x.Sub(p.arenaStart) / 512
		h := &p.heapInfo[i]
		if h.base == 0 {  
			return
		}
		x = h.base.Add(x.Sub(h.base) / h.size * h.size)
		off := uint64(x.Sub(p.arenaStart))
		j := off / 512
		h = &p.heapInfo[j]
		b := off % 512 / 8
		if h.mark&(uint64(1)<<b) != 0 {  
			return
		}
		h.mark |= uint64(1) << b
		n++
		live += h.size
		q = append(q, Object(x))
	}
	for _, g := range p.goroutines {
		for _, f := range g.frames {
			for a := range f.Live {
				add(p.proc.ReadPtr(a))
			}
		}
	}
	for _, m := range p.modules {
		for _, s := range [2]string{"data", "bss"} {
			min := core.Address(m.r.Field(s).Uintptr())
			max := core.Address(m.r.Field("e" + s).Uintptr())
			gc := m.r.Field("gc" + s + "mask").Field("bytedata").Address()
			num := max.Sub(min) / ptrSize
			for i := int64(0); i < num; i++ {
				if p.proc.ReadUint8(gc.Add(i/8))>>uint(i%8)&1 != 0 {
					add(p.proc.ReadPtr(min.Add(i * ptrSize)))
				}
			}
		}
	}
	for _, r := range p.globals {
		if !strings.HasPrefix(r.Name, "finalizer for ") {
			continue
		}
		for _, f := range r.Type.Fields {
			if f.Type.Kind == KindPtr {
				add(p.proc.ReadPtr(r.Addr.Add(f.Off)))
			}
		}
	}
	for len(q) > 0 {
		x := q[len(q)-1]
		q = q[:len(q)-1]
		size := p.Size(x)
		for i := int64(0); i < size; i += ptrSize {
			a := core.Address(x).Add(i)
			if p.isPtr(a) {
				add(p.proc.ReadPtr(a))
			}
		}
	}
	p.nObj = n
	for i := len(p.heapInfo) - 1; i >= 0; i-- {
		h := &p.heapInfo[i]
		if h.mark == 0 {  
			continue
		}
		n -= bits.OnesCount64(h.mark)
		h.firstIdx = n
	}
	alloc := p.Stats().Child("heap").Child("in use spans").Child("alloc")
	alloc.Children = []*Stats{
		&Stats{"live", live, nil},
		&Stats{"garbage", alloc.Size - live, nil},
	}
}
func (p *Process) isPtr(a core.Address) bool {
	off := a.Sub(p.arenaStart)
	off >>= p.proc.LogPtrSize()
	return p.proc.ReadUint8(p.bitmapEnd.Add(-(off>>2)-1))>>uint(off&3)&1 != 0
}
func (p *Process) IsPtr(a core.Address) bool {
	if a >= p.arenaStart && a < p.arenaUsed {
		return p.isPtr(a)
	}
	for _, m := range p.modules {
		for _, s := range [2]string{"data", "bss"} {
			min := core.Address(m.r.Field(s).Uintptr())
			max := core.Address(m.r.Field("e" + s).Uintptr())
			if a < min || a >= max {
				continue
			}
			gc := m.r.Field("gc" + s + "mask").Field("bytedata").Address()
			i := a.Sub(min)
			return p.proc.ReadUint8(gc.Add(i/8))>>uint(i%8) != 0
		}
	}
	return false
}
func (p *Process) FindObject(a core.Address) (Object, int64) {
	if a < p.arenaStart || a >= p.arenaUsed {
		return 0, 0
	}
	h := &p.heapInfo[a.Sub(p.arenaStart)/512]
	if h.size == 0 {
		return 0, 0
	}
	x := h.base.Add(a.Sub(h.base) / h.size * h.size)
	h = &p.heapInfo[x.Sub(p.arenaStart)/512]
	if h.mark>>(uint64(x)%512/8)&1 == 0 {
		return 0, 0
	}
	return Object(x), a.Sub(x)
}
func (p *Process) findObjectIndex(a core.Address) (int, int64) {
	x, off := p.FindObject(a)
	if x == 0 {
		return -1, 0
	}
	h := &p.heapInfo[core.Address(x).Sub(p.arenaStart)/512]
	return h.firstIdx + bits.OnesCount64(h.mark&(uint64(1)<<(uint64(x)%512/8)-1)), off
}
func (p *Process) ForEachObject(fn func(x Object) bool) {
	for i := 0; i < len(p.heapInfo); i++ {
		m := p.heapInfo[i].mark
		for m != 0 {
			j := bits.TrailingZeros64(m)
			m &= m - 1
			if !fn(Object(p.arenaStart.Add(int64(i)*512 + int64(j)*8))) {
				return
			}
		}
	}
}
func (p *Process) ForEachRoot(fn func(r *Root) bool) {
	for _, r := range p.globals {
		if !fn(r) {
			return
		}
	}
	for _, g := range p.goroutines {
		for _, f := range g.frames {
			for _, r := range f.roots {
				if !fn(r) {
					return
				}
			}
		}
	}
}
func (p *Process) Addr(x Object) core.Address {
	return core.Address(x)
}