| | |
| | |
| | |
| |
|
| | package maps |
| |
|
| | import ( |
| | "internal/abi" |
| | "unsafe" |
| | ) |
| |
|
| | type CtrlGroup = ctrlGroup |
| |
|
| | const DebugLog = debugLog |
| |
|
| | var AlignUpPow2 = alignUpPow2 |
| |
|
| | const MaxTableCapacity = maxTableCapacity |
| | const MaxAvgGroupLoad = maxAvgGroupLoad |
| |
|
| | |
| | |
| | const maxAllocTest = 1 << 30 |
| |
|
| | func newTestMapType[K comparable, V any]() *abi.MapType { |
| | var m map[K]V |
| | mTyp := abi.TypeOf(m) |
| | mt := (*abi.MapType)(unsafe.Pointer(mTyp)) |
| | return mt |
| | } |
| |
|
| | func NewTestMap[K comparable, V any](hint uintptr) (*Map, *abi.MapType) { |
| | mt := newTestMapType[K, V]() |
| | return NewMap(mt, hint, nil, maxAllocTest), mt |
| | } |
| |
|
| | func (m *Map) TableCount() int { |
| | if m.dirLen <= 0 { |
| | return 0 |
| | } |
| | return m.dirLen |
| | } |
| |
|
| | |
| | func (m *Map) GroupCount() uint64 { |
| | if m.dirLen <= 0 { |
| | if m.dirPtr == nil { |
| | return 0 |
| | } |
| | return 1 |
| | } |
| |
|
| | var n uint64 |
| | var lastTab *table |
| | for i := range m.dirLen { |
| | t := m.directoryAt(uintptr(i)) |
| | if t == lastTab { |
| | continue |
| | } |
| | lastTab = t |
| | n += t.groups.lengthMask + 1 |
| | } |
| | return n |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func (m *Map) KeyFromFullGroup(typ *abi.MapType) unsafe.Pointer { |
| | if m.dirLen <= 0 { |
| | return nil |
| | } |
| |
|
| | var lastTab *table |
| | for i := range m.dirLen { |
| | t := m.directoryAt(uintptr(i)) |
| | if t == lastTab { |
| | continue |
| | } |
| | lastTab = t |
| |
|
| | for i := uint64(0); i <= t.groups.lengthMask; i++ { |
| | g := t.groups.group(typ, i) |
| | match := g.ctrls().matchEmpty() |
| | if match != 0 { |
| | continue |
| | } |
| |
|
| | |
| | for j := uintptr(0); j < abi.MapGroupSlots; j++ { |
| | if g.ctrls().get(j) == ctrlDeleted { |
| | continue |
| | } |
| | slotKey := g.key(typ, j) |
| | if typ.IndirectKey() { |
| | slotKey = *((*unsafe.Pointer)(slotKey)) |
| | } |
| | return slotKey |
| | } |
| | } |
| | } |
| |
|
| | return nil |
| | } |
| |
|
| | |
| | func (m *Map) TableFor(typ *abi.MapType, key unsafe.Pointer) *table { |
| | if m.dirLen <= 0 { |
| | return nil |
| | } |
| |
|
| | hash := typ.Hasher(key, m.seed) |
| | idx := m.directoryIndex(hash) |
| | return m.directoryAt(idx) |
| | } |
| |
|
| | func (t *table) GrowthLeft() uint64 { |
| | return uint64(t.growthLeft) |
| | } |
| |
|
| | |
| | func (t *table) GroupsStart() unsafe.Pointer { |
| | return t.groups.data |
| | } |
| |
|
| | |
| | func (t *table) GroupsLength() uintptr { |
| | return uintptr(t.groups.lengthMask + 1) |
| | } |
| |
|