Example #1
0
func prepare() {
	// group objects by type
	fmt.Println("Grouping by type...")
	byType = make([]bucket, len(d.FTList))
	for i := 0; i < d.NumObjects(); i++ {
		x := read.ObjId(i)
		tid := d.Ft(x).Id
		b := byType[tid]
		b.bytes += d.Size(x)
		b.objects = append(b.objects, x)
		byType[tid] = b
	}

	// compute referrers
	fmt.Println("Computing referrers...")
	ref1 = make([]read.ObjId, d.NumObjects())
	for i := 0; i < d.NumObjects(); i++ {
		ref1[i] = read.ObjNil
	}
	ref2 = map[read.ObjId][]read.ObjId{}
	for i := 0; i < d.NumObjects(); i++ {
		x := read.ObjId(i)
		//fmt.Printf("object %d %x %d %s %s\n", i, d.Addr(x), d.Size(x), d.Ft(x).GCSig, d.Ft(x).Name)
		//printbytes(d.Contents(x))
		for _, e := range d.Edges(x) {
			r := ref1[e.To]
			if r == read.ObjNil {
				ref1[e.To] = x
			} else if x != r {
				s := ref2[e.To]
				if len(s) == 0 || x != s[len(s)-1] {
					ref2[e.To] = append(s, x)
				}
			}
		}
	}

	dom()
}
Example #2
0
func objHandler(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	v := q["id"]
	if len(v) != 1 {
		http.Error(w, "id parameter missing", 405)
		return
	}
	id, err := strconv.ParseUint(v[0], 10, 64)
	if err != nil {
		http.Error(w, err.Error(), 405)
		return
	}

	if int(id) >= d.NumObjects() {
		http.Error(w, "object not found", 405)
		return
	}
	x := read.ObjId(id)

	fld := getFields(d.Contents(x), d.Ft(x).Fields, d.Edges(x))
	if len(fld) > maxFields {
		msg := fmt.Sprintf("<font color=Red>elided for display: %d fields</font>", len(fld)-(maxFields-1))
		fld = fld[:maxFields-1]
		fld = append(fld, Field{msg, "", ""})
	}

	ref := getReferrers(x)
	if len(ref) > maxFields {
		msg := fmt.Sprintf("<font color=Red>elided for display: %d referrers</font>", len(ref)-(maxFields-1))
		ref = ref[:maxFields-1]
		ref = append(ref, msg)
	}

	info := objInfo{
		d.Addr(x),
		typeLink(d.Ft(x)),
		d.Size(x),
		fld,
		ref,
		domsize[x],
	}
	if err := objTemplate.Execute(w, info); err != nil {
		log.Print(err)
	}
}
Example #3
0
func dom() {
	fmt.Println("Computing dominators...")
	n := d.NumObjects()

	// make list of roots
	// TODO: have loader compute this?
	roots := map[read.ObjId]struct{}{}
	for _, s := range []*read.Data{d.Data, d.Bss} {
		for _, e := range s.Edges {
			roots[e.To] = struct{}{}
		}
	}
	for _, f := range d.Frames {
		for _, e := range f.Edges {
			roots[e.To] = struct{}{}
		}
	}
	for _, x := range d.Otherroots {
		for _, e := range x.Edges {
			roots[e.To] = struct{}{}
		}
	}

	// compute postorder traversal
	// object states:
	// 0 - not seen yet
	// 1 - seen, added to queue, not yet expanded children
	// 2 - seen, already expanded children
	// 3 - added to postorder
	postorder := make([]read.ObjId, 0, n)
	postnum := make([]int, n+1)
	state := make([]byte, n)
	var q []read.ObjId // stack of work to do, holds state 1 and 2 objects
	for x := range roots {
		if state[x] != 0 {
			if state[x] != 3 {
				log.Fatal("bad state found")
			}
			continue
		}
		state[x] = 1
		q = q[:0]
		q = append(q, x)
		for len(q) > 0 {
			y := q[len(q)-1]
			if state[y] == 2 {
				state[y] = 3
				q = q[:len(q)-1]
				postnum[y] = len(postorder)
				postorder = append(postorder, y)
			} else {
				if state[y] != 1 {
					log.Fatal("bad state")
				}
				state[y] = 2
				for _, e := range d.Edges(y) {
					z := e.To
					if state[z] == 0 {
						state[z] = 1
						q = append(q, z)
					}
				}
			}
		}
	}
	postnum[n] = n // virtual start node

	// compute immediate dominators
	// http://www.hipersoft.rice.edu/grads/publications/dom14.pdf
	idom := make([]read.ObjId, n+1)
	for i := 0; i < n; i++ {
		idom[i] = read.ObjNil
	}
	idom[n] = read.ObjId(n)
	for r := range roots {
		idom[r] = read.ObjId(n)
	}
	var redges []read.ObjId
	change := true
	for change {
		change = false
		for i := len(postorder) - 1; i >= 0; i-- {
			x := postorder[i]
			// get list of incoming edges
			redges = redges[:0]
			if ref1[x] != read.ObjNil {
				redges = append(redges, ref1[x])
				redges = append(redges, ref2[x]...)
			}
			a := read.ObjNil
			for _, b := range redges {
				if idom[b] == read.ObjNil {
					continue
				}
				if a == read.ObjNil {
					a = b
					continue
				}
				for a != b {
					if postnum[a] < postnum[b] {
						a = idom[a]
					} else {
						b = idom[b]
					}
				}
			}
			if _, ok := roots[x]; ok {
				a = read.ObjId(n)
			}
			if a != idom[x] {
				idom[x] = a
				change = true
			}
		}
	}

	domsize = make([]uint64, n+1)
	for _, x := range postorder {
		domsize[x] += d.Size(x)
		domsize[idom[x]] += domsize[x]
	}
	// Note: unreachable objects will have domsize of 0.
}