// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package maps implements Go's builtin map type.
package maps import ( ) const debugLog = false func ( *table) ( *abi.SwissMapType, *Map) { if !debugLog { return } // For every non-empty slot, verify we can retrieve the key using Get. // Count the number of used and deleted slots. var uint16 var uint16 var uint16 for := uint64(0); <= .groups.lengthMask; ++ { := .groups.group(, ) for := uintptr(0); < abi.SwissMapGroupSlots; ++ { := .ctrls().get() switch { case == ctrlDeleted: ++ case == ctrlEmpty: ++ default: ++ := .key(, ) if .IndirectKey() { = *((*unsafe.Pointer)()) } // Can't lookup keys that don't compare equal // to themselves (e.g., NaN). if !.Key.Equal(, ) { continue } if , := .Get(, , ); ! { := .Hasher(, .seed) print("invariant failed: slot(", , "/", , "): key ") dump(, .Key.Size_) print(" not found [hash=", , ", h2=", h2(), " h1=", h1(), "]\n") .Print(, ) panic("invariant failed: slot: key not found") } } } } if != .used { print("invariant failed: found ", , " used slots, but used count is ", .used, "\n") .Print(, ) panic("invariant failed: found mismatched used slot count") } := (.capacity*maxAvgGroupLoad)/abi.SwissMapGroupSlots - .used - if != .growthLeft { print("invariant failed: found ", .growthLeft, " growthLeft, but expected ", , "\n") .Print(, ) panic("invariant failed: found mismatched growthLeft") } if != .tombstones() { print("invariant failed: found ", , " tombstones, but expected ", .tombstones(), "\n") .Print(, ) panic("invariant failed: found mismatched tombstones") } if == 0 { print("invariant failed: found no empty slots (violates probe invariant)\n") .Print(, ) panic("invariant failed: found no empty slots (violates probe invariant)") } } func ( *table) ( *abi.SwissMapType, *Map) { print(`table{ index: `, .index, ` localDepth: `, .localDepth, ` capacity: `, .capacity, ` used: `, .used, ` growthLeft: `, .growthLeft, ` groups: `) for := uint64(0); <= .groups.lengthMask; ++ { print("\t\tgroup ", , "\n") := .groups.group(, ) := .ctrls() for := uintptr(0); < abi.SwissMapGroupSlots; ++ { print("\t\t\tslot ", , "\n") := .get() print("\t\t\t\tctrl ", ) switch { case ctrlEmpty: print(" (empty)\n") case ctrlDeleted: print(" (deleted)\n") default: print("\n") } print("\t\t\t\tkey ") dump(.key(, ), .Key.Size_) println("") print("\t\t\t\telem ") dump(.elem(, ), .Elem.Size_) println("") } } } // TODO(prattmic): not in hex because print doesn't have a way to print in hex // outside the runtime. func dump( unsafe.Pointer, uintptr) { for > 0 { print(*(*byte)(), " ") = unsafe.Pointer(uintptr() + 1) -- } }