package maps
import (
"internal/abi"
"unsafe"
)
const debugLog = false
func (t *table ) checkInvariants (typ *abi .SwissMapType , m *Map ) {
if !debugLog {
return
}
var used uint16
var deleted uint16
var empty uint16
for i := uint64 (0 ); i <= t .groups .lengthMask ; i ++ {
g := t .groups .group (typ , i )
for j := uintptr (0 ); j < abi .SwissMapGroupSlots ; j ++ {
c := g .ctrls ().get (j )
switch {
case c == ctrlDeleted :
deleted ++
case c == ctrlEmpty :
empty ++
default :
used ++
key := g .key (typ , j )
if typ .IndirectKey () {
key = *((*unsafe .Pointer )(key ))
}
if !typ .Key .Equal (key , key ) {
continue
}
if _ , ok := t .Get (typ , m , key ); !ok {
hash := typ .Hasher (key , m .seed )
print ("invariant failed: slot(" , i , "/" , j , "): key " )
dump (key , typ .Key .Size_ )
print (" not found [hash=" , hash , ", h2=" , h2 (hash ), " h1=" , h1 (hash ), "]\n" )
t .Print (typ , m )
panic ("invariant failed: slot: key not found" )
}
}
}
}
if used != t .used {
print ("invariant failed: found " , used , " used slots, but used count is " , t .used , "\n" )
t .Print (typ , m )
panic ("invariant failed: found mismatched used slot count" )
}
growthLeft := (t .capacity *maxAvgGroupLoad )/abi .SwissMapGroupSlots - t .used - deleted
if growthLeft != t .growthLeft {
print ("invariant failed: found " , t .growthLeft , " growthLeft, but expected " , growthLeft , "\n" )
t .Print (typ , m )
panic ("invariant failed: found mismatched growthLeft" )
}
if deleted != t .tombstones () {
print ("invariant failed: found " , deleted , " tombstones, but expected " , t .tombstones (), "\n" )
t .Print (typ , m )
panic ("invariant failed: found mismatched tombstones" )
}
if empty == 0 {
print ("invariant failed: found no empty slots (violates probe invariant)\n" )
t .Print (typ , m )
panic ("invariant failed: found no empty slots (violates probe invariant)" )
}
}
func (t *table ) Print (typ *abi .SwissMapType , m *Map ) {
print (`table{
index: ` , t .index , `
localDepth: ` , t .localDepth , `
capacity: ` , t .capacity , `
used: ` , t .used , `
growthLeft: ` , t .growthLeft , `
groups:
` )
for i := uint64 (0 ); i <= t .groups .lengthMask ; i ++ {
print ("\t\tgroup " , i , "\n" )
g := t .groups .group (typ , i )
ctrls := g .ctrls ()
for j := uintptr (0 ); j < abi .SwissMapGroupSlots ; j ++ {
print ("\t\t\tslot " , j , "\n" )
c := ctrls .get (j )
print ("\t\t\t\tctrl " , c )
switch c {
case ctrlEmpty :
print (" (empty)\n" )
case ctrlDeleted :
print (" (deleted)\n" )
default :
print ("\n" )
}
print ("\t\t\t\tkey " )
dump (g .key (typ , j ), typ .Key .Size_ )
println ("" )
print ("\t\t\t\telem " )
dump (g .elem (typ , j ), typ .Elem .Size_ )
println ("" )
}
}
}
func dump(ptr unsafe .Pointer , size uintptr ) {
for size > 0 {
print (*(*byte )(ptr ), " " )
ptr = unsafe .Pointer (uintptr (ptr ) + 1 )
size --
}
}
The pages are generated with Golds v0.7.3-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .