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 defines the constraint optimiser ("pre-solver").
13
func (a *analysis) optimize() {
16
// TODO(adonovan): opt:
17
// PE, LE, HVN, HRU, sparse bitsets, etc.
20
// renumber permutes a.nodes so that all nodes within an addressable
21
// object appear before all non-addressable nodes, maintaining the
22
// order of nodes within the same object (as required by offsetAddr).
24
// renumber must update every nodeid in the analysis (constraints,
25
// Pointers, callgraph, etc) to reflect the new ordering.
27
// This is an optimisation to increase the locality and efficiency of
28
// sparse representations of points-to sets. (Typically only about
29
// 20% of nodes are within an object.)
31
// NB: nodes added during solving (e.g. for reflection, SetFinalizer)
32
// will be appended to the end.
34
func (a *analysis) renumber() {
35
N := nodeid(len(a.nodes))
36
newNodes := make([]*node, N, N)
37
renumbering := make([]nodeid, N, N) // maps old to new
41
// The zero node is special.
42
newNodes[j] = a.nodes[i]
47
// Pass 1: object nodes.
55
end := i + nodeid(obj.size)
57
newNodes[j] = a.nodes[i]
65
// Pass 2: non-object nodes.
73
newNodes[j] = a.nodes[i]
80
panic(fmt.Sprintf("internal error: j=%d, N=%d", j, N))
83
// Log the remapping table.
85
fmt.Fprintf(a.log, "Renumbering nodes to improve density:\n")
86
fmt.Fprintf(a.log, "(%d object nodes of %d total)\n", nobj, N)
87
for old, new := range renumbering {
88
fmt.Fprintf(a.log, "\tn%d -> n%d\n", old, new)
92
// Now renumber all existing nodeids to use the new node permutation.
93
// It is critical that all reachable nodeids are accounted for!
95
// Renumber nodeids in queried Pointers.
96
for v, ptr := range a.result.Queries {
97
ptr.n = renumbering[ptr.n]
98
a.result.Queries[v] = ptr
100
for v, ptr := range a.result.IndirectQueries {
101
ptr.n = renumbering[ptr.n]
102
a.result.IndirectQueries[v] = ptr
105
// Renumber nodeids in global objects.
106
for v, id := range a.globalobj {
107
a.globalobj[v] = renumbering[id]
110
// Renumber nodeids in constraints.
111
for _, c := range a.constraints {
112
c.renumber(renumbering)
115
// Renumber nodeids in the call graph.
116
for _, cgn := range a.cgnodes {
117
cgn.obj = renumbering[cgn.obj]
118
for _, site := range cgn.sites {
119
site.targets = renumbering[site.targets]