go.tools/oracle: callgraph: fix crash caused by sparse node numbering.

Revision 0ea4058a1ca3 caused the node numbering to become
sparse, violating a precondition of
(*callgraphResult).toSerial.  Now we renumber the callgraph
nodes always, not just the qpos != nil case.

Fixes golang/go#8171

LGTM=crawshaw
R=crawshaw
CC=golang-codereviews
https://golang.org/cl/103240044
This commit is contained in:
Alan Donovan 2014-06-10 12:36:40 -04:00
parent afea1b1755
commit 95e5e90454
1 changed files with 33 additions and 33 deletions

View File

@ -26,52 +26,52 @@ func doCallgraph(o *Oracle, qpos *QueryPos) (queryResult, error) {
cg.DeleteSyntheticNodes() cg.DeleteSyntheticNodes()
var qpkg *types.Package var qpkg *types.Package
var roots []*callgraph.Node var isQueryPkg func(fn *ssa.Function) bool
var keep, remove, roots []*callgraph.Node
if qpos == nil { if qpos == nil {
// No -pos provided: show complete callgraph. // No -pos provided: show complete callgraph.
roots = append(roots, cg.Root) roots = append(roots, cg.Root)
isQueryPkg = func(fn *ssa.Function) bool { return true }
} else { } else {
// A query -pos was provided: restrict result to // A query -pos was provided: restrict result to
// functions belonging to the query package. // functions belonging to the query package.
qpkg = qpos.info.Pkg qpkg = qpos.info.Pkg
isQueryPkg := func(fn *ssa.Function) bool { isQueryPkg = func(fn *ssa.Function) bool {
return fn.Pkg != nil && fn.Pkg.Object == qpkg return fn.Pkg != nil && fn.Pkg.Object == qpkg
} }
}
// First compute the nodes to keep and remove. // First compute the nodes to keep and remove.
var nodes, remove []*callgraph.Node for fn, cgn := range cg.Nodes {
for fn, cgn := range cg.Nodes { if isQueryPkg(fn) {
if isQueryPkg(fn) { keep = append(keep, cgn)
nodes = append(nodes, cgn) } else {
} else { remove = append(remove, cgn)
remove = append(remove, cgn) }
}
// Compact the Node.ID sequence of the kept nodes,
// preserving the original order.
sort.Sort(nodesByID(keep))
for i, cgn := range keep {
cgn.ID = i
}
// Compute the set of roots:
// in-package nodes with out-of-package callers.
// For determinism, roots are ordered by original Node.ID.
for _, cgn := range keep {
for _, e := range cgn.In {
if !isQueryPkg(e.Caller.Func) {
roots = append(roots, cgn)
break
} }
} }
}
// Compact the Node.ID sequence of the remaining // Finally, discard all out-of-package nodes.
// nodes, preserving the original order. for _, cgn := range remove {
sort.Sort(nodesByID(nodes)) cg.DeleteNode(cgn)
for i, cgn := range nodes {
cgn.ID = i
}
// Compute the set of roots:
// in-package nodes with out-of-package callers.
// For determinism, roots are ordered by original Node.ID.
for _, cgn := range nodes {
for _, e := range cgn.In {
if !isQueryPkg(e.Caller.Func) {
roots = append(roots, cgn)
break
}
}
}
// Finally, discard all out-of-package nodes.
for _, cgn := range remove {
cg.DeleteNode(cgn)
}
} }
return &callgraphResult{qpkg, cg.Nodes, roots}, nil return &callgraphResult{qpkg, cg.Nodes, roots}, nil