github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/callgraph/vta/internal/trie/builder.go (about)

     1  // Copyright 2021 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.
     4  
     5  package trie
     6  
     7  // Collision functions combine a left and right hand side (lhs and rhs) values
     8  // the two values are associated with the same key and produces the value that
     9  // will be stored for the key.
    10  //
    11  // Collision functions must be idempotent:
    12  //
    13  //	collision(x, x) == x for all x.
    14  //
    15  // Collisions functions may be applied whenever a value is inserted
    16  // or two maps are merged, or intersected.
    17  type Collision func(lhs interface{}, rhs interface{}) interface{}
    18  
    19  // TakeLhs always returns the left value in a collision.
    20  func TakeLhs(lhs, rhs interface{}) interface{} { return lhs }
    21  
    22  // TakeRhs always returns the right hand side in a collision.
    23  func TakeRhs(lhs, rhs interface{}) interface{} { return rhs }
    24  
    25  // Builder creates new Map. Each Builder has a unique Scope.
    26  //
    27  // IMPORTANT:  Nodes are hash-consed internally to reduce memory consumption. To
    28  // support hash-consing Builders keep an internal Map of all of the Maps that they
    29  // have created. To GC any of the Maps created by the Builder, all references to
    30  // the Builder must be dropped. This includes MutMaps.
    31  type Builder struct {
    32  	scope Scope
    33  
    34  	// hash-consing maps for each node type.
    35  	empty    *empty
    36  	leaves   map[leaf]*leaf
    37  	branches map[branch]*branch
    38  	// It may be possible to support more types of patricia tries
    39  	// (e.g. non-hash-consed) by making Builder an interface and abstracting
    40  	// the mkLeaf and mkBranch functions.
    41  }
    42  
    43  // NewBuilder creates a new Builder with a unique Scope.
    44  func NewBuilder() *Builder {
    45  	s := newScope()
    46  	return &Builder{
    47  		scope:    s,
    48  		empty:    &empty{s},
    49  		leaves:   make(map[leaf]*leaf),
    50  		branches: make(map[branch]*branch),
    51  	}
    52  }
    53  
    54  func (b *Builder) Scope() Scope { return b.scope }
    55  
    56  // Rescope changes the builder's scope to a new unique Scope.
    57  //
    58  // Any Maps created using the previous scope need to be Cloned
    59  // before any operation.
    60  //
    61  // This makes the old internals of the Builder eligible to be GC'ed.
    62  func (b *Builder) Rescope() {
    63  	s := newScope()
    64  	b.scope = s
    65  	b.empty = &empty{s}
    66  	b.leaves = make(map[leaf]*leaf)
    67  	b.branches = make(map[branch]*branch)
    68  }
    69  
    70  // Empty is the empty map.
    71  func (b *Builder) Empty() Map { return Map{b.Scope(), b.empty} }
    72  
    73  // InsertWith inserts a new association from k to v into the Map m to create a new map
    74  // in the current scope and handle collisions using the collision function c.
    75  //
    76  // This is roughly corresponds to updating a map[uint64]interface{} by:
    77  //
    78  //	if _, ok := m[k]; ok { m[k] = c(m[k], v} else { m[k] = v}
    79  //
    80  // An insertion or update happened whenever Insert(m, ...) != m .
    81  func (b *Builder) InsertWith(c Collision, m Map, k uint64, v interface{}) Map {
    82  	m = b.Clone(m)
    83  	return Map{b.Scope(), b.insert(c, m.n, b.mkLeaf(key(k), v), false)}
    84  }
    85  
    86  // Inserts a new association from key to value into the Map m to create
    87  // a new map in the current scope.
    88  //
    89  // If there was a previous value mapped by key, keep the previously mapped value.
    90  // This is roughly corresponds to updating a map[uint64]interface{} by:
    91  //
    92  //	if _, ok := m[k]; ok { m[k] = val }
    93  //
    94  // This is equivalent to b.Merge(m, b.Create({k: v})).
    95  func (b *Builder) Insert(m Map, k uint64, v interface{}) Map {
    96  	return b.InsertWith(TakeLhs, m, k, v)
    97  }
    98  
    99  // Updates a (key, value) in the map. This is roughly corresponds to
   100  // updating a map[uint64]interface{} by:
   101  //
   102  //	m[key] = val
   103  func (b *Builder) Update(m Map, key uint64, val interface{}) Map {
   104  	return b.InsertWith(TakeRhs, m, key, val)
   105  }
   106  
   107  // Merge two maps lhs and rhs to create a new map in the current scope.
   108  //
   109  // Whenever there is a key in both maps (a collision), the resulting value mapped by
   110  // the key will be `c(lhs[key], rhs[key])`.
   111  func (b *Builder) MergeWith(c Collision, lhs, rhs Map) Map {
   112  	lhs, rhs = b.Clone(lhs), b.Clone(rhs)
   113  	return Map{b.Scope(), b.merge(c, lhs.n, rhs.n)}
   114  }
   115  
   116  // Merge two maps lhs and rhs to create a new map in the current scope.
   117  //
   118  // Whenever there is a key in both maps (a collision), the resulting value mapped by
   119  // the key will be the value in lhs `b.Collision(lhs[key], rhs[key])`.
   120  func (b *Builder) Merge(lhs, rhs Map) Map {
   121  	return b.MergeWith(TakeLhs, lhs, rhs)
   122  }
   123  
   124  // Clone returns a Map that contains the same (key, value) elements
   125  // within b.Scope(), i.e. return m if m.Scope() == b.Scope() or return
   126  // a deep copy of m within b.Scope() otherwise.
   127  func (b *Builder) Clone(m Map) Map {
   128  	if m.Scope() == b.Scope() {
   129  		return m
   130  	} else if m.n == nil {
   131  		return Map{b.Scope(), b.empty}
   132  	}
   133  	return Map{b.Scope(), b.clone(m.n)}
   134  }
   135  func (b *Builder) clone(n node) node {
   136  	switch n := n.(type) {
   137  	case *empty:
   138  		return b.empty
   139  	case *leaf:
   140  		return b.mkLeaf(n.k, n.v)
   141  	case *branch:
   142  		return b.mkBranch(n.prefix, n.branching, b.clone(n.left), b.clone(n.right))
   143  	default:
   144  		panic("unreachable")
   145  	}
   146  }
   147  
   148  // Remove a key from a Map m and return the resulting Map.
   149  func (b *Builder) Remove(m Map, k uint64) Map {
   150  	m = b.Clone(m)
   151  	return Map{b.Scope(), b.remove(m.n, key(k))}
   152  }
   153  
   154  // Intersect Maps lhs and rhs and returns a map with all of the keys in
   155  // both lhs and rhs and the value comes from lhs, i.e.
   156  //
   157  //	{(k, lhs[k]) | k in lhs, k in rhs}.
   158  func (b *Builder) Intersect(lhs, rhs Map) Map {
   159  	return b.IntersectWith(TakeLhs, lhs, rhs)
   160  }
   161  
   162  // IntersectWith take lhs and rhs and returns the intersection
   163  // with the value coming from the collision function, i.e.
   164  //
   165  //	{(k, c(lhs[k], rhs[k]) ) | k in lhs, k in rhs}.
   166  //
   167  // The elements of the resulting map are always { <k, c(lhs[k], rhs[k]) > }
   168  // for each key k that a key in both lhs and rhs.
   169  func (b *Builder) IntersectWith(c Collision, lhs, rhs Map) Map {
   170  	l, r := b.Clone(lhs), b.Clone(rhs)
   171  	return Map{b.Scope(), b.intersect(c, l.n, r.n)}
   172  }
   173  
   174  // MutMap is a convenient wrapper for a Map and a *Builder that will be used to create
   175  // new Maps from it.
   176  type MutMap struct {
   177  	B *Builder
   178  	M Map
   179  }
   180  
   181  // MutEmpty is an empty MutMap for a builder.
   182  func (b *Builder) MutEmpty() MutMap {
   183  	return MutMap{b, b.Empty()}
   184  }
   185  
   186  // Insert an element into the map using the collision function for the builder.
   187  // Returns true if the element was inserted.
   188  func (mm *MutMap) Insert(k uint64, v interface{}) bool {
   189  	old := mm.M
   190  	mm.M = mm.B.Insert(old, k, v)
   191  	return old != mm.M
   192  }
   193  
   194  // Updates an element in the map. Returns true if the map was updated.
   195  func (mm *MutMap) Update(k uint64, v interface{}) bool {
   196  	old := mm.M
   197  	mm.M = mm.B.Update(old, k, v)
   198  	return old != mm.M
   199  }
   200  
   201  // Removes a key from the map. Returns true if the element was removed.
   202  func (mm *MutMap) Remove(k uint64) bool {
   203  	old := mm.M
   204  	mm.M = mm.B.Remove(old, k)
   205  	return old != mm.M
   206  }
   207  
   208  // Merge another map into the current one using the collision function
   209  // for the builder. Returns true if the map changed.
   210  func (mm *MutMap) Merge(other Map) bool {
   211  	old := mm.M
   212  	mm.M = mm.B.Merge(old, other)
   213  	return old != mm.M
   214  }
   215  
   216  // Intersect another map into the current one using the collision function
   217  // for the builder. Returns true if the map changed.
   218  func (mm *MutMap) Intersect(other Map) bool {
   219  	old := mm.M
   220  	mm.M = mm.B.Intersect(old, other)
   221  	return old != mm.M
   222  }
   223  
   224  func (b *Builder) Create(m map[uint64]interface{}) Map {
   225  	var leaves []*leaf
   226  	for k, v := range m {
   227  		leaves = append(leaves, b.mkLeaf(key(k), v))
   228  	}
   229  	return Map{b.Scope(), b.create(leaves)}
   230  }
   231  
   232  // Merge another map into the current one using the collision function
   233  // for the builder. Returns true if the map changed.
   234  func (mm *MutMap) MergeWith(c Collision, other Map) bool {
   235  	old := mm.M
   236  	mm.M = mm.B.MergeWith(c, old, other)
   237  	return old != mm.M
   238  }
   239  
   240  // creates a map for a collection of leaf nodes.
   241  func (b *Builder) create(leaves []*leaf) node {
   242  	n := len(leaves)
   243  	if n == 0 {
   244  		return b.empty
   245  	} else if n == 1 {
   246  		return leaves[0]
   247  	}
   248  	// Note: we can do a more sophisicated algorithm by:
   249  	// - sorting the leaves ahead of time,
   250  	// - taking the prefix and branching bit of the min and max key,
   251  	// - binary searching for the branching bit,
   252  	// - splitting exactly where the branch will be, and
   253  	// - making the branch node for this prefix + branching bit.
   254  	// Skipping until this is a performance bottleneck.
   255  
   256  	m := n / 2 // (n >= 2) ==> 1 <= m < n
   257  	l, r := leaves[:m], leaves[m:]
   258  	return b.merge(nil, b.create(l), b.create(r))
   259  }
   260  
   261  // mkLeaf returns the hash-consed representative of (k, v) in the current scope.
   262  func (b *Builder) mkLeaf(k key, v interface{}) *leaf {
   263  	l := &leaf{k: k, v: v}
   264  	if rep, ok := b.leaves[*l]; ok {
   265  		return rep
   266  	}
   267  	b.leaves[*l] = l
   268  	return l
   269  }
   270  
   271  // mkBranch returns the hash-consed representative of the tuple
   272  //
   273  //	(prefix, branch, left, right)
   274  //
   275  // in the current scope.
   276  func (b *Builder) mkBranch(p prefix, bp bitpos, left node, right node) *branch {
   277  	br := &branch{
   278  		sz:        left.size() + right.size(),
   279  		prefix:    p,
   280  		branching: bp,
   281  		left:      left,
   282  		right:     right,
   283  	}
   284  	if rep, ok := b.branches[*br]; ok {
   285  		return rep
   286  	}
   287  	b.branches[*br] = br
   288  	return br
   289  }
   290  
   291  // join two maps with prefixes p0 and p1 that are *known* to disagree.
   292  func (b *Builder) join(p0 prefix, t0 node, p1 prefix, t1 node) *branch {
   293  	m := branchingBit(p0, p1)
   294  	var left, right node
   295  	if zeroBit(p0, m) {
   296  		left, right = t0, t1
   297  	} else {
   298  		left, right = t1, t0
   299  	}
   300  	prefix := mask(p0, m)
   301  	return b.mkBranch(prefix, m, left, right)
   302  }
   303  
   304  // collide two leaves with the same key to create a leaf
   305  // with the collided value.
   306  func (b *Builder) collide(c Collision, left, right *leaf) *leaf {
   307  	if left == right {
   308  		return left // c is idempotent: c(x, x) == x
   309  	}
   310  	val := left.v // keep the left value by default if c is nil
   311  	if c != nil {
   312  		val = c(left.v, right.v)
   313  	}
   314  	switch val {
   315  	case left.v:
   316  		return left
   317  	case right.v:
   318  		return right
   319  	default:
   320  		return b.mkLeaf(left.k, val)
   321  	}
   322  }
   323  
   324  // inserts a leaf l into a map m and returns the resulting map.
   325  // When lhs is true, l is the left hand side in a collision.
   326  // Both l and m are in the current scope.
   327  func (b *Builder) insert(c Collision, m node, l *leaf, lhs bool) node {
   328  	switch m := m.(type) {
   329  	case *empty:
   330  		return l
   331  	case *leaf:
   332  		if m.k == l.k {
   333  			left, right := l, m
   334  			if !lhs {
   335  				left, right = right, left
   336  			}
   337  			return b.collide(c, left, right)
   338  		}
   339  		return b.join(prefix(l.k), l, prefix(m.k), m)
   340  	case *branch:
   341  		// fallthrough
   342  	}
   343  	// m is a branch
   344  	br := m.(*branch)
   345  	if !matchPrefix(prefix(l.k), br.prefix, br.branching) {
   346  		return b.join(prefix(l.k), l, br.prefix, br)
   347  	}
   348  	var left, right node
   349  	if zeroBit(prefix(l.k), br.branching) {
   350  		left, right = b.insert(c, br.left, l, lhs), br.right
   351  	} else {
   352  		left, right = br.left, b.insert(c, br.right, l, lhs)
   353  	}
   354  	if left == br.left && right == br.right {
   355  		return m
   356  	}
   357  	return b.mkBranch(br.prefix, br.branching, left, right)
   358  }
   359  
   360  // merge two maps in the current scope.
   361  func (b *Builder) merge(c Collision, lhs, rhs node) node {
   362  	if lhs == rhs {
   363  		return lhs
   364  	}
   365  	switch lhs := lhs.(type) {
   366  	case *empty:
   367  		return rhs
   368  	case *leaf:
   369  		return b.insert(c, rhs, lhs, true)
   370  	case *branch:
   371  		switch rhs := rhs.(type) {
   372  		case *empty:
   373  			return lhs
   374  		case *leaf:
   375  			return b.insert(c, lhs, rhs, false)
   376  		case *branch:
   377  			// fallthrough
   378  		}
   379  	}
   380  
   381  	// Last remaining case is branch branch merging.
   382  	// For brevity, we adopt the Okasaki and Gill naming conventions
   383  	// for branching and prefixes.
   384  	s, t := lhs.(*branch), rhs.(*branch)
   385  	p, m := s.prefix, s.branching
   386  	q, n := t.prefix, t.branching
   387  
   388  	if m == n && p == q { // prefixes are identical.
   389  		left, right := b.merge(c, s.left, t.left), b.merge(c, s.right, t.right)
   390  		return b.mkBranch(p, m, left, right)
   391  	}
   392  	if !prefixesOverlap(p, m, q, n) {
   393  		return b.join(p, s, q, t) // prefixes are disjoint.
   394  	}
   395  	// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)
   396  	// By prefixesOverlap(...), either:
   397  	//   higher(m, n) && matchPrefix(q, p, m), or
   398  	//   higher(n, m) && matchPrefix(p, q, n)
   399  	// So either s or t may can be merged with one branch or the other.
   400  	switch {
   401  	case ord(m, n) && zeroBit(q, m):
   402  		return b.mkBranch(p, m, b.merge(c, s.left, t), s.right)
   403  	case ord(m, n) && !zeroBit(q, m):
   404  		return b.mkBranch(p, m, s.left, b.merge(c, s.right, t))
   405  	case ord(n, m) && zeroBit(p, n):
   406  		return b.mkBranch(q, n, b.merge(c, s, t.left), t.right)
   407  	default:
   408  		return b.mkBranch(q, n, t.left, b.merge(c, s, t.right))
   409  	}
   410  }
   411  
   412  func (b *Builder) remove(m node, k key) node {
   413  	switch m := m.(type) {
   414  	case *empty:
   415  		return m
   416  	case *leaf:
   417  		if m.k == k {
   418  			return b.empty
   419  		}
   420  		return m
   421  	case *branch:
   422  		// fallthrough
   423  	}
   424  	br := m.(*branch)
   425  	kp := prefix(k)
   426  	if !matchPrefix(kp, br.prefix, br.branching) {
   427  		// The prefix does not match. kp is not in br.
   428  		return br
   429  	}
   430  	// the prefix matches. try to remove from the left or right branch.
   431  	left, right := br.left, br.right
   432  	if zeroBit(kp, br.branching) {
   433  		left = b.remove(left, k) // k may be in the left branch.
   434  	} else {
   435  		right = b.remove(right, k) // k may be in the right branch.
   436  	}
   437  	if left == br.left && right == br.right {
   438  		return br // no update
   439  	} else if _, ok := left.(*empty); ok {
   440  		return right // left updated and is empty.
   441  	} else if _, ok := right.(*empty); ok {
   442  		return left // right updated and is empty.
   443  	}
   444  	// Either left or right updated. Both left and right are not empty.
   445  	// The left and right branches still share the same prefix and disagree
   446  	// on the same branching bit. It is safe to directly create the branch.
   447  	return b.mkBranch(br.prefix, br.branching, left, right)
   448  }
   449  
   450  func (b *Builder) intersect(c Collision, l, r node) node {
   451  	if l == r {
   452  		return l
   453  	}
   454  	switch l := l.(type) {
   455  	case *empty:
   456  		return b.empty
   457  	case *leaf:
   458  		if rleaf := r.find(l.k); rleaf != nil {
   459  			return b.collide(c, l, rleaf)
   460  		}
   461  		return b.empty
   462  	case *branch:
   463  		switch r := r.(type) {
   464  		case *empty:
   465  			return b.empty
   466  		case *leaf:
   467  			if lleaf := l.find(r.k); lleaf != nil {
   468  				return b.collide(c, lleaf, r)
   469  			}
   470  			return b.empty
   471  		case *branch:
   472  			// fallthrough
   473  		}
   474  	}
   475  	// Last remaining case is branch branch intersection.
   476  	s, t := l.(*branch), r.(*branch)
   477  	p, m := s.prefix, s.branching
   478  	q, n := t.prefix, t.branching
   479  
   480  	if m == n && p == q {
   481  		// prefixes are identical.
   482  		left, right := b.intersect(c, s.left, t.left), b.intersect(c, s.right, t.right)
   483  		if _, ok := left.(*empty); ok {
   484  			return right
   485  		} else if _, ok := right.(*empty); ok {
   486  			return left
   487  		}
   488  		// The left and right branches are both non-empty.
   489  		// They still share the same prefix and disagree on the same branching bit.
   490  		// It is safe to directly create the branch.
   491  		return b.mkBranch(p, m, left, right)
   492  	}
   493  
   494  	if !prefixesOverlap(p, m, q, n) {
   495  		return b.empty // The prefixes share no keys.
   496  	}
   497  	// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)
   498  	// By prefixesOverlap(...), either:
   499  	//   ord(m, n) && matchPrefix(q, p, m), or
   500  	//   ord(n, m) && matchPrefix(p, q, n)
   501  	// So either s or t may be a strict subtree of the other.
   502  	var lhs, rhs node
   503  	switch {
   504  	case ord(m, n) && zeroBit(q, m):
   505  		lhs, rhs = s.left, t
   506  	case ord(m, n) && !zeroBit(q, m):
   507  		lhs, rhs = s.right, t
   508  	case ord(n, m) && zeroBit(p, n):
   509  		lhs, rhs = s, t.left
   510  	default:
   511  		lhs, rhs = s, t.right
   512  	}
   513  	return b.intersect(c, lhs, rhs)
   514  }