compiler: implement clear builtin for maps
Этот коммит содержится в:
родитель
a2f886a67a
коммит
f1e25a18d2
7 изменённых файлов: 64 добавлений и 0 удалений
|
@ -1631,6 +1631,10 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||
}, "")
|
||||
call.AddCallSiteAttribute(1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(elementAlign)))
|
||||
|
||||
return llvm.Value{}, nil
|
||||
case *types.Map:
|
||||
m := argValues[0]
|
||||
b.createMapClear(m)
|
||||
return llvm.Value{}, nil
|
||||
default:
|
||||
return llvm.Value{}, b.makeError(pos, "unsupported type in clear builtin: "+typ.String())
|
||||
|
|
|
@ -185,6 +185,11 @@ func (b *builder) createMapDelete(keyType types.Type, m, key llvm.Value, pos tok
|
|||
}
|
||||
}
|
||||
|
||||
// Clear the given map.
|
||||
func (b *builder) createMapClear(m llvm.Value) {
|
||||
b.createRuntimeCall("hashmapClear", []llvm.Value{m}, "")
|
||||
}
|
||||
|
||||
// createMapIteratorNext lowers the *ssa.Next instruction for iterating over a
|
||||
// map. It returns a tuple of {bool, key, value} with the result of the
|
||||
// iteration.
|
||||
|
|
4
compiler/testdata/go1.21.go
предоставленный
4
compiler/testdata/go1.21.go
предоставленный
|
@ -59,3 +59,7 @@ func clearSlice(s []int) {
|
|||
func clearZeroSizedSlice(s []struct{}) {
|
||||
clear(s)
|
||||
}
|
||||
|
||||
func clearMap(m map[string]int) {
|
||||
clear(m)
|
||||
}
|
||||
|
|
9
compiler/testdata/go1.21.ll
предоставленный
9
compiler/testdata/go1.21.ll
предоставленный
|
@ -147,6 +147,15 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #2 {
|
||||
entry:
|
||||
call void @runtime.hashmapClear(ptr %m, ptr undef) #5
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1
|
||||
|
||||
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
|
||||
declare i32 @llvm.smin.i32(i32, i32) #4
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
11
testdata/go1.21.go
предоставленный
11
testdata/go1.21.go
предоставленный
|
@ -15,4 +15,15 @@ func main() {
|
|||
s := []int{1, 2, 3, 4, 5}
|
||||
clear(s[:3])
|
||||
println("cleared s[:3]:", s[0], s[1], s[2], s[3], s[4])
|
||||
|
||||
// The clear builtin, for maps.
|
||||
m := map[int]string{
|
||||
1: "one",
|
||||
2: "two",
|
||||
3: "three",
|
||||
}
|
||||
clear(m)
|
||||
println("cleared map:", m[1], m[2], m[3], len(m))
|
||||
m[4] = "four"
|
||||
println("added to cleared map:", m[1], m[2], m[3], m[4], len(m))
|
||||
}
|
||||
|
|
2
testdata/go1.21.txt
предоставленный
2
testdata/go1.21.txt
предоставленный
|
@ -1,3 +1,5 @@
|
|||
min/max: -3 5
|
||||
min/max: -3.000000e+000 +5.000000e+000
|
||||
cleared s[:3]: 0 0 0 4 5
|
||||
cleared map: 0
|
||||
added to cleared map: four 1
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче