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,40 +26,41 @@ 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) {
nodes = append(nodes, cgn) keep = append(keep, cgn)
} else { } else {
remove = append(remove, cgn) remove = append(remove, cgn)
} }
} }
// Compact the Node.ID sequence of the remaining // Compact the Node.ID sequence of the kept nodes,
// nodes, preserving the original order. // preserving the original order.
sort.Sort(nodesByID(nodes)) sort.Sort(nodesByID(keep))
for i, cgn := range nodes { for i, cgn := range keep {
cgn.ID = i cgn.ID = i
} }
// Compute the set of roots: // Compute the set of roots:
// in-package nodes with out-of-package callers. // in-package nodes with out-of-package callers.
// For determinism, roots are ordered by original Node.ID. // For determinism, roots are ordered by original Node.ID.
for _, cgn := range nodes { for _, cgn := range keep {
for _, e := range cgn.In { for _, e := range cgn.In {
if !isQueryPkg(e.Caller.Func) { if !isQueryPkg(e.Caller.Func) {
roots = append(roots, cgn) roots = append(roots, cgn)
@ -72,7 +73,6 @@ func doCallgraph(o *Oracle, qpos *QueryPos) (queryResult, error) {
for _, cgn := range remove { for _, cgn := range remove {
cg.DeleteNode(cgn) cg.DeleteNode(cgn)
} }
}
return &callgraphResult{qpkg, cg.Nodes, roots}, nil return &callgraphResult{qpkg, cg.Nodes, roots}, nil
} }