| // 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. |
| |
| //go:build goexperiment.swissmap |
| |
| package runtime |
| |
| import ( |
| "internal/abi" |
| "unsafe" |
| ) |
| |
| func MapBucketsCount(m map[int]int) int { |
| h := *(**hmap)(unsafe.Pointer(&m)) |
| return 1 << h.B |
| } |
| |
| func MapBucketsPointerIsNil(m map[int]int) bool { |
| h := *(**hmap)(unsafe.Pointer(&m)) |
| return h.buckets == nil |
| } |
| |
| func MapTombstoneCheck(m map[int]int) { |
| // Make sure emptyOne and emptyRest are distributed correctly. |
| // We should have a series of filled and emptyOne cells, followed by |
| // a series of emptyRest cells. |
| h := *(**hmap)(unsafe.Pointer(&m)) |
| i := any(m) |
| t := *(**maptype)(unsafe.Pointer(&i)) |
| |
| for x := 0; x < 1<<h.B; x++ { |
| b0 := (*bmap)(add(h.buckets, uintptr(x)*uintptr(t.BucketSize))) |
| n := 0 |
| for b := b0; b != nil; b = b.overflow(t) { |
| for i := 0; i < abi.SwissMapBucketCount; i++ { |
| if b.tophash[i] != emptyRest { |
| n++ |
| } |
| } |
| } |
| k := 0 |
| for b := b0; b != nil; b = b.overflow(t) { |
| for i := 0; i < abi.SwissMapBucketCount; i++ { |
| if k < n && b.tophash[i] == emptyRest { |
| panic("early emptyRest") |
| } |
| if k >= n && b.tophash[i] != emptyRest { |
| panic("late non-emptyRest") |
| } |
| if k == n-1 && b.tophash[i] == emptyOne { |
| panic("last non-emptyRest entry is emptyOne") |
| } |
| k++ |
| } |
| } |
| } |
| } |