Source file src/internal/runtime/maps/export_test.go

     1  // Copyright 2024 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 maps
     6  
     7  import (
     8  	"internal/abi"
     9  	"unsafe"
    10  )
    11  
    12  type CtrlGroup = ctrlGroup
    13  
    14  const DebugLog = debugLog
    15  
    16  var AlignUpPow2 = alignUpPow2
    17  
    18  const MaxTableCapacity = maxTableCapacity
    19  const MaxAvgGroupLoad = maxAvgGroupLoad
    20  
    21  // This isn't equivalent to runtime.maxAlloc. It is fine for basic testing but
    22  // we can't properly test hint alloc overflows with this.
    23  const maxAllocTest = 1 << 30
    24  
    25  func NewTestMap[K comparable, V any](hint uintptr) (*Map, *abi.SwissMapType) {
    26  	mt := newTestMapType[K, V]()
    27  	return NewMap(mt, hint, nil, maxAllocTest), mt
    28  }
    29  
    30  func (m *Map) TableCount() int {
    31  	if m.dirLen <= 0 {
    32  		return 0
    33  	}
    34  	return m.dirLen
    35  }
    36  
    37  // Total group count, summed across all tables.
    38  func (m *Map) GroupCount() uint64 {
    39  	if m.dirLen <= 0 {
    40  		if m.dirPtr == nil {
    41  			return 0
    42  		}
    43  		return 1
    44  	}
    45  
    46  	var n uint64
    47  	var lastTab *table
    48  	for i := range m.dirLen {
    49  		t := m.directoryAt(uintptr(i))
    50  		if t == lastTab {
    51  			continue
    52  		}
    53  		lastTab = t
    54  		n += t.groups.lengthMask + 1
    55  	}
    56  	return n
    57  }
    58  
    59  // Return a key from a group containing no empty slots.
    60  //
    61  // Returns nil if there are no full groups.
    62  // Returns nil if a group is full but contains entirely deleted slots.
    63  // Returns nil if the map is small.
    64  func (m *Map) KeyFromFullGroup(typ *abi.SwissMapType) unsafe.Pointer {
    65  	if m.dirLen <= 0 {
    66  		return nil
    67  	}
    68  
    69  	var lastTab *table
    70  	for i := range m.dirLen {
    71  		t := m.directoryAt(uintptr(i))
    72  		if t == lastTab {
    73  			continue
    74  		}
    75  		lastTab = t
    76  
    77  		for i := uint64(0); i <= t.groups.lengthMask; i++ {
    78  			g := t.groups.group(typ, i)
    79  			match := g.ctrls().matchEmpty()
    80  			if match != 0 {
    81  				continue
    82  			}
    83  
    84  			// All full or deleted slots.
    85  			for j := uintptr(0); j < abi.SwissMapGroupSlots; j++ {
    86  				if g.ctrls().get(j) == ctrlDeleted {
    87  					continue
    88  				}
    89  				slotKey := g.key(typ, j)
    90  				if typ.IndirectKey() {
    91  					slotKey = *((*unsafe.Pointer)(slotKey))
    92  				}
    93  				return slotKey
    94  			}
    95  		}
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  // Returns nil if the map is small.
   102  func (m *Map) TableFor(typ *abi.SwissMapType, key unsafe.Pointer) *table {
   103  	if m.dirLen <= 0 {
   104  		return nil
   105  	}
   106  
   107  	hash := typ.Hasher(key, m.seed)
   108  	idx := m.directoryIndex(hash)
   109  	return m.directoryAt(idx)
   110  }
   111  
   112  func (t *table) GrowthLeft() uint64 {
   113  	return uint64(t.growthLeft)
   114  }
   115  
   116  // Returns the start address of the groups array.
   117  func (t *table) GroupsStart() unsafe.Pointer {
   118  	return t.groups.data
   119  }
   120  
   121  // Returns the length of the groups array.
   122  func (t *table) GroupsLength() uintptr {
   123  	return uintptr(t.groups.lengthMask + 1)
   124  }
   125  

View as plain text