runtime: only check for pointers up to ptrdata, not size

Change-Id: I166cf253b7f2483d652c98d2fba36c380e2f3347
Reviewed-on: https://go-review.googlesource.com/c/go/+/227177
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Ian Lance Taylor 2020-04-02 17:14:25 -07:00
parent 8e121b1587
commit 08dd4ad7e3
2 changed files with 21 additions and 5 deletions

View file

@ -158,7 +158,7 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
return
}
if typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(dst), uintptr(src), typ.size)
bulkBarrierPreWrite(uintptr(dst), uintptr(src), typ.ptrdata)
}
// There's a race here: if some other goroutine can write to
// src, it may change some pointer in src after we've
@ -198,12 +198,27 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size
if writeBarrier.needed && typ.ptrdata != 0 && size >= sys.PtrSize {
// Pointer-align start address for bulk barrier.
adst, asrc, asize := dst, src, size
ptrdata := typ.ptrdata
if ptrdata > off {
ptrdata -= off
} else {
ptrdata = 0
}
if frag := -off & (sys.PtrSize - 1); frag != 0 {
adst = add(dst, frag)
asrc = add(src, frag)
asize -= frag
if ptrdata > frag {
ptrdata -= frag
} else {
ptrdata = 0
}
}
bulkBarrierPreWrite(uintptr(adst), uintptr(asrc), asize&^(sys.PtrSize-1))
pwsize := asize &^ (sys.PtrSize - 1)
if pwsize > ptrdata {
pwsize = ptrdata
}
bulkBarrierPreWrite(uintptr(adst), uintptr(asrc), pwsize)
}
memmove(dst, src, size)
@ -270,7 +285,8 @@ func typedslicecopy(typ *_type, dst, src slice) int {
// before calling typedslicecopy.
size := uintptr(n) * typ.size
if writeBarrier.needed {
bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), size)
pwsize := size - typ.size + typ.ptrdata
bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), pwsize)
}
// See typedmemmove for a discussion of the race between the
// barrier and memmove.
@ -318,7 +334,7 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
//go:nosplit
func typedmemclr(typ *_type, ptr unsafe.Pointer) {
if typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(ptr), 0, typ.size)
bulkBarrierPreWrite(uintptr(ptr), 0, typ.ptrdata)
}
memclrNoHeapPointers(ptr, typ.size)
}

View file

@ -182,7 +182,7 @@ func growslice(et *_type, old slice, cap int) slice {
if lenmem > 0 && writeBarrier.enabled {
// Only shade the pointers in old.array since we know the destination slice p
// only contains nil pointers because it has been cleared during alloc.
bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem)
bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem-et.size+et.ptrdata)
}
}
memmove(p, old.array, lenmem)