diff options
author | Ayke van Laethem <[email protected]> | 2023-07-07 15:47:49 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-08-04 11:59:11 +0200 |
commit | f1e25a18d2584cda1d7b2d478e17a4358ee7daf0 (patch) | |
tree | 1cee732b73801015de741855ad047c71fcf3fa4a /src | |
parent | a2f886a67a645add0c2e42289e20f89fe402294d (diff) | |
download | tinygo-f1e25a18d2584cda1d7b2d478e17a4358ee7daf0.tar.gz tinygo-f1e25a18d2584cda1d7b2d478e17a4358ee7daf0.zip |
compiler: implement clear builtin for maps
Diffstat (limited to 'src')
-rw-r--r-- | src/runtime/hashmap.go | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index 8a902a55d..dfbec300e 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -91,6 +91,35 @@ func hashmapMakeUnsafePointer(keySize, valueSize uintptr, sizeHint uintptr, alg return (unsafe.Pointer)(hashmapMake(keySize, valueSize, sizeHint, alg)) } +// Remove all entries from the map, without actually deallocating the space for +// it. This is used for the clear builtin, and can be used to reuse a map (to +// avoid extra heap allocations). +func hashmapClear(m *hashmap) { + if m == nil { + // Nothing to do. According to the spec: + // > If the map or slice is nil, clear is a no-op. + return + } + + m.count = 0 + numBuckets := uintptr(1) << m.bucketBits + bucketSize := hashmapBucketSize(m) + for i := uintptr(0); i < numBuckets; i++ { + bucket := hashmapBucketAddr(m, m.buckets, i) + for bucket != nil { + // Clear the tophash, to mark these keys/values as removed. + bucket.tophash = [8]uint8{} + + // Clear the keys and values in the bucket so that the GC won't pin + // these allocations. + memzero(unsafe.Add(unsafe.Pointer(bucket), unsafe.Sizeof(hashmapBucket{})), bucketSize-unsafe.Sizeof(hashmapBucket{})) + + // Move on to the next bucket in the chain. + bucket = bucket.next + } + } +} + func hashmapKeyEqualAlg(alg hashmapAlgorithm) func(x, y unsafe.Pointer, n uintptr) bool { switch alg { case hashmapAlgorithmBinary: |