go/pointer: use sparse bit vectors to represent points-to sets in solver.

This optimization reduces solve time (typically >90% of the
total) by about 78% when analysing real programs.  It also
makes the solver 100% deterministic since all iterations are
ordered.

Also:
- remove unnecessary nodeid parameter to solve() method.
- don't add a fieldInfo for singleton tuples (cosmetic fix).
- inline+simplify "worklist" type.
- replace "constraintset" type by a slice.

LGTM=crawshaw
R=crawshaw
CC=golang-codereviews
https://golang.org/cl/95240043
diff --git a/go/pointer/analysis.go b/go/pointer/analysis.go
index 699462b..884962b 100644
--- a/go/pointer/analysis.go
+++ b/go/pointer/analysis.go
@@ -99,7 +99,7 @@
 	// - *typeFilterConstraint y=x.(I)
 	// - *untagConstraint      y=x.(C)
 	// - *invokeConstraint     y=x.f(params...)
-	complex constraintset
+	complex []constraint
 }
 
 // An analysis instance holds the state of a single pointer analysis problem.
@@ -119,9 +119,10 @@
 	globalobj   map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
 	localval    map[ssa.Value]nodeid        // node for each local ssa.Value
 	localobj    map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
-	work        worklist                    // solver's worklist
+	work        nodeset                     // solver's worklist
 	result      *Result                     // results of the analysis
 	track       track                       // pointerlike types whose aliasing we track
+	deltaSpace  []int                       // working space for iterating over PTS deltas
 
 	// Reflection & intrinsics:
 	hasher              typeutil.Hasher // cache of type hashes
@@ -223,11 +224,11 @@
 		trackTypes:  make(map[types.Type]bool),
 		hasher:      typeutil.MakeHasher(),
 		intrinsics:  make(map[*ssa.Function]intrinsic),
-		work:        makeMapWorklist(),
 		result: &Result{
 			Queries:         make(map[ssa.Value]Pointer),
 			IndirectQueries: make(map[ssa.Value]Pointer),
 		},
+		deltaSpace: make([]int, 0, 100),
 	}
 
 	if false {
@@ -300,10 +301,11 @@
 	}
 
 	// Add dynamic edges to call graph.
+	var space [100]int
 	for _, caller := range a.cgnodes {
 		for _, site := range caller.sites {
-			for callee := range a.nodes[site.targets].pts {
-				a.callEdge(caller, site, callee)
+			for _, callee := range a.nodes[site.targets].pts.AppendTo(space[:0]) {
+				a.callEdge(caller, site, nodeid(callee))
 			}
 		}
 	}