1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // This file implements renumbering, a pre-solver optimization to
8 // improve the efficiency of the solver's points-to set representation.
10 // TODO(adonovan): rename file "renumber.go"
14 // renumber permutes a.nodes so that all nodes within an addressable
15 // object appear before all non-addressable nodes, maintaining the
16 // order of nodes within the same object (as required by offsetAddr).
18 // renumber must update every nodeid in the analysis (constraints,
19 // Pointers, callgraph, etc) to reflect the new ordering.
21 // This is an optimisation to increase the locality and efficiency of
22 // sparse representations of points-to sets. (Typically only about
23 // 20% of nodes are within an object.)
25 // NB: nodes added during solving (e.g. for reflection, SetFinalizer)
26 // will be appended to the end.
28 // Renumbering makes the PTA log inscrutable. To aid debugging, later
29 // phases (e.g. HVN) must not rely on it having occurred.
31 func (a *analysis) renumber() {
33 fmt.Fprintf(a.log, "\n\n==== Renumbering\n\n")
36 N := nodeid(len(a.nodes))
37 newNodes := make([]*node, N)
38 renumbering := make([]nodeid, N) // maps old to new
42 // The zero node is special.
43 newNodes[j] = a.nodes[i]
48 // Pass 1: object nodes.
56 end := i + nodeid(obj.size)
58 newNodes[j] = a.nodes[i]
66 // Pass 2: non-object nodes.
74 newNodes[j] = a.nodes[i]
81 panic(fmt.Sprintf("internal error: j=%d, N=%d", j, N))
84 // Log the remapping table.
86 fmt.Fprintf(a.log, "Renumbering nodes to improve density:\n")
87 fmt.Fprintf(a.log, "(%d object nodes of %d total)\n", nobj, N)
88 for old, new := range renumbering {
89 fmt.Fprintf(a.log, "\tn%d -> n%d\n", old, new)
93 // Now renumber all existing nodeids to use the new node permutation.
94 // It is critical that all reachable nodeids are accounted for!
96 // Renumber nodeids in queried Pointers.
97 for v, ptr := range a.result.Queries {
98 ptr.n = renumbering[ptr.n]
99 a.result.Queries[v] = ptr
101 for v, ptr := range a.result.IndirectQueries {
102 ptr.n = renumbering[ptr.n]
103 a.result.IndirectQueries[v] = ptr
105 for _, queries := range a.config.extendedQueries {
106 for _, query := range queries {
107 if query.ptr != nil {
108 query.ptr.n = renumbering[query.ptr.n]
113 // Renumber nodeids in global objects.
114 for v, id := range a.globalobj {
115 a.globalobj[v] = renumbering[id]
118 // Renumber nodeids in constraints.
119 for _, c := range a.constraints {
120 c.renumber(renumbering)
123 // Renumber nodeids in the call graph.
124 for _, cgn := range a.cgnodes {
125 cgn.obj = renumbering[cgn.obj]
126 for _, site := range cgn.sites {
127 site.targets = renumbering[site.targets]