]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: only clear pointer-containing memory during map delete
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 21 Aug 2017 18:00:31 +0000 (11:00 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Wed, 23 Aug 2017 13:53:00 +0000 (13:53 +0000)
When deleting entries from a map, only clear the key and value
if they contain pointers. And use memclrHasPointers to do so.

While we're here, specialize key clearing in mapdelete_faststr,
and fix another missed usage of add in mapdelete.

Benchmarking impeded by #21546.

Change-Id: I3f6f924f738d6b899b722d6438e9e63f52359b84
Reviewed-on: https://go-review.googlesource.com/57630
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/hashmap.go
src/runtime/hashmap_fast.go

index 1cfa9070fb7a179d085fdf374e3635c9bb2d291f..60af870fac2db6a26c9e0ee4ae6c377cec702ddb 100644 (file)
@@ -681,16 +681,20 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
                        if !alg.equal(key, k2) {
                                continue
                        }
+                       // Only clear key if there are pointers in it.
                        if t.indirectkey {
                                *(*unsafe.Pointer)(k) = nil
-                       } else {
-                               typedmemclr(t.key, k)
+                       } else if t.key.kind&kindNoPointers == 0 {
+                               memclrHasPointers(k, t.key.size)
                        }
-                       v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
-                       if t.indirectvalue {
-                               *(*unsafe.Pointer)(v) = nil
-                       } else {
-                               typedmemclr(t.elem, v)
+                       // Only clear value if there are pointers in it.
+                       if t.indirectvalue || t.elem.kind&kindNoPointers == 0 {
+                               v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+                               if t.indirectvalue {
+                                       *(*unsafe.Pointer)(v) = nil
+                               } else {
+                                       memclrHasPointers(v, t.elem.size)
+                               }
                        }
                        b.tophash[i] = empty
                        h.count--
index 2fda9f425550d2308a928dd105ecf2376bac374a..64f9dc4c2ad647711160a6de48fca705ce02e528 100644 (file)
@@ -652,9 +652,15 @@ func mapdelete_fast32(t *maptype, h *hmap, key uint32) {
                        if key != *(*uint32)(k) || b.tophash[i] == empty {
                                continue
                        }
-                       typedmemclr(t.key, unsafe.Pointer(k))
-                       v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*4 + i*uintptr(t.valuesize))
-                       typedmemclr(t.elem, v)
+                       // Only clear key if there are pointers in it.
+                       if t.key.kind&kindNoPointers == 0 {
+                               memclrHasPointers(k, t.key.size)
+                       }
+                       // Only clear value if there are pointers in it.
+                       if t.elem.kind&kindNoPointers == 0 {
+                               v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*4 + i*uintptr(t.valuesize))
+                               memclrHasPointers(v, t.elem.size)
+                       }
                        b.tophash[i] = empty
                        h.count--
                        goto done
@@ -699,9 +705,15 @@ func mapdelete_fast64(t *maptype, h *hmap, key uint64) {
                        if key != *(*uint64)(k) || b.tophash[i] == empty {
                                continue
                        }
-                       typedmemclr(t.key, unsafe.Pointer(k))
-                       v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*8 + i*uintptr(t.valuesize))
-                       typedmemclr(t.elem, v)
+                       // Only clear key if there are pointers in it.
+                       if t.key.kind&kindNoPointers == 0 {
+                               memclrHasPointers(k, t.key.size)
+                       }
+                       // Only clear value if there are pointers in it.
+                       if t.elem.kind&kindNoPointers == 0 {
+                               v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*8 + i*uintptr(t.valuesize))
+                               memclrHasPointers(v, t.elem.size)
+                       }
                        b.tophash[i] = empty
                        h.count--
                        goto done
@@ -752,9 +764,12 @@ func mapdelete_faststr(t *maptype, h *hmap, ky string) {
                        if k.str != key.str && !memequal(k.str, key.str, uintptr(key.len)) {
                                continue
                        }
-                       typedmemclr(t.key, unsafe.Pointer(k))
-                       v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*2*sys.PtrSize + i*uintptr(t.valuesize))
-                       typedmemclr(t.elem, v)
+                       *(*string)(kptr) = ""
+                       // Only clear value if there are pointers in it.
+                       if t.elem.kind&kindNoPointers == 0 {
+                               v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*2*sys.PtrSize + i*uintptr(t.valuesize))
+                               memclrHasPointers(v, t.elem.size)
+                       }
                        b.tophash[i] = empty
                        h.count--
                        goto done