Found with GODEBUG=wbshadow=2 mode.
Eventually that will run automatically, but right now
it still detects other missing write barriers.
Change-Id: Iea83d693480c2f3008b4e80d55821acff65970a6
Reviewed-on: https://go-review.googlesource.com/2277
Reviewed-by: Keith Randall <khr@golang.org>
recvg := sg.g
if sg.elem != nil {
- memmove(unsafe.Pointer(sg.elem), ep, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, unsafe.Pointer(sg.elem), ep)
sg.elem = nil
}
recvg.param = unsafe.Pointer(sg)
raceacquire(chanbuf(c, c.sendx))
racerelease(chanbuf(c, c.sendx))
}
- memmove(chanbuf(c, c.sendx), ep, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, chanbuf(c, c.sendx), ep)
c.sendx++
if c.sendx == c.dataqsiz {
c.sendx = 0
unlock(&c.lock)
if ep != nil {
- memmove(ep, sg.elem, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, ep, sg.elem)
}
sg.elem = nil
gp := sg.g
racerelease(chanbuf(c, c.recvx))
}
if ep != nil {
- memmove(ep, chanbuf(c, c.recvx), uintptr(c.elemsize))
+ typedmemmove(c.elemtype, ep, chanbuf(c, c.recvx))
}
memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
continue
}
// already have a mapping for key. Update it.
- memmove(k2, key, uintptr(t.key.size))
+ typedmemmove(t.key, k2, key)
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
v2 := v
if t.indirectvalue {
v2 = *((*unsafe.Pointer)(v2))
}
- memmove(v2, val, uintptr(t.elem.size))
+ typedmemmove(t.elem, v2, val)
return
}
ovf := b.overflow(t)
*(*unsafe.Pointer)(insertv) = vmem
insertv = vmem
}
- memmove(insertk, key, uintptr(t.key.size))
- memmove(insertv, val, uintptr(t.elem.size))
+ typedmemmove(t.key, insertk, key)
+ typedmemmove(t.elem, insertv, val)
*inserti = top
h.count++
}
if t.indirectkey {
*(*unsafe.Pointer)(xk) = k2 // copy pointer
} else {
- memmove(xk, k, uintptr(t.key.size)) // copy value
+ typedmemmove(t.key, xk, k) // copy value
}
if t.indirectvalue {
*(*unsafe.Pointer)(xv) = *(*unsafe.Pointer)(v)
} else {
- memmove(xv, v, uintptr(t.elem.size))
+ typedmemmove(t.elem, xv, v)
}
xi++
xk = add(xk, uintptr(t.keysize))
if t.indirectkey {
*(*unsafe.Pointer)(yk) = k2
} else {
- memmove(yk, k, uintptr(t.key.size))
+ typedmemmove(t.key, yk, k)
}
if t.indirectvalue {
*(*unsafe.Pointer)(yv) = *(*unsafe.Pointer)(v)
} else {
- memmove(yv, v, uintptr(t.elem.size))
+ typedmemmove(t.elem, yv, v)
}
yi++
yk = add(yk, uintptr(t.keysize))
}
func convT2E(t *_type, elem unsafe.Pointer) (e interface{}) {
- size := uintptr(t.size)
ep := (*eface)(unsafe.Pointer(&e))
if isDirectIface(t) {
ep._type = t
- memmove(unsafe.Pointer(&ep.data), elem, size)
+ typedmemmove(t, unsafe.Pointer(&ep.data), elem)
} else {
x := newobject(t)
// TODO: We allocate a zeroed object only to overwrite it with
// actual data. Figure out how to avoid zeroing. Also below in convT2I.
- memmove(x, elem, size)
+ typedmemmove(t, x, elem)
ep._type = t
ep.data = x
}
tab = getitab(inter, t, false)
atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
}
- size := uintptr(t.size)
pi := (*iface)(unsafe.Pointer(&i))
if isDirectIface(t) {
pi.tab = tab
- memmove(unsafe.Pointer(&pi.data), elem, size)
+ typedmemmove(t, unsafe.Pointer(&pi.data), elem)
} else {
x := newobject(t)
- memmove(x, elem, size)
+ typedmemmove(t, x, elem)
pi.tab = tab
pi.data = x
}
if tab._type != t {
panic(&TypeAssertionError{*tab.inter.typ._string, *tab._type._string, *t._string, ""})
}
- size := uintptr(t.size)
+ // NOTE(rsc): If this changes to take a pointer argument
+ // instead of using &r, these calls need to change to be
+ // typedmemmove (the first can be just writebarrierptr).
+ // Until then, it is very important that no blocking operation
+ // happens between the memmove and the return.
if isDirectIface(t) {
- memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), size)
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), uintptr(t.size))
} else {
- memmove(unsafe.Pointer(&r), ip.data, size)
+ memmove(unsafe.Pointer(&r), ip.data, uintptr(t.size))
}
return
}
//go:nosplit
func assertI2T2(t *_type, i fInterface) (r byte) {
ip := (*iface)(unsafe.Pointer(&i))
- size := uintptr(t.size)
- ok := (*bool)(add(unsafe.Pointer(&r), size))
+ ok := (*bool)(add(unsafe.Pointer(&r), uintptr(t.size)))
tab := ip.tab
if tab == nil || tab._type != t {
*ok = false
- memclr(unsafe.Pointer(&r), size)
+ memclr(unsafe.Pointer(&r), uintptr(t.size))
return
}
*ok = true
+ // NOTE(rsc): If this changes to take a pointer argument
+ // instead of using &r, these calls need to change to be
+ // typedmemmove (the first can be just writebarrierptr).
+ // Until then, it is very important that no blocking operation
+ // happens between the memmove and the return.
if isDirectIface(t) {
- memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), size)
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ip.data), uintptr(t.size))
} else {
- memmove(unsafe.Pointer(&r), ip.data, size)
+ memmove(unsafe.Pointer(&r), ip.data, uintptr(t.size))
}
return
}
if ep._type != t {
panic(&TypeAssertionError{"", *ep._type._string, *t._string, ""})
}
- size := uintptr(t.size)
+ // NOTE(rsc): If this changes to take a pointer argument
+ // instead of using &r, these calls need to change to be
+ // typedmemmove (the first can be just writebarrierptr).
+ // Until then, it is very important that no blocking operation
+ // happens between the memmove and the return.
if isDirectIface(t) {
- memmove(unsafe.Pointer(&r), unsafe.Pointer(&ep.data), size)
+ memmove(unsafe.Pointer(&r), unsafe.Pointer(&ep.data), uintptr(t.size))
} else {
- memmove(unsafe.Pointer(&r), ep.data, size)
+ memmove(unsafe.Pointer(&r), ep.data, uintptr(t.size))
}
return
}
return
}
*ok = true
+ // NOTE(rsc): If this changes to take a pointer argument
+ // instead of using &r, these calls need to change to be
+ // typedmemmove (the first can be just writebarrierptr).
+ // Until then, it is very important that no blocking operation
+ // happens between the memmove and the return.
if isDirectIface(t) {
memmove(unsafe.Pointer(&r), unsafe.Pointer(&ep.data), size)
} else {
} else {
*(*uintptr)(dst) = *(*uintptr)(src)
}
- dst = add(dst, ptrSize)
- src = add(src, ptrSize)
+ // TODO(rsc): The noescape calls should be unnecessary.
+ dst = add(noescape(dst), ptrSize)
+ src = add(noescape(src), ptrSize)
if i+1 == nptr {
break
}
} else {
*(*uintptr)(dst) = *(*uintptr)(src)
}
- dst = add(dst, ptrSize)
- src = add(src, ptrSize)
+ dst = add(noescape(dst), ptrSize)
+ src = add(noescape(src), ptrSize)
}
})
}
*cas.receivedp = true
}
if cas.elem != nil {
- memmove(cas.elem, chanbuf(c, c.recvx), uintptr(c.elemsize))
+ typedmemmove(c.elemtype, cas.elem, chanbuf(c, c.recvx))
}
memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
c.recvx++
racerelease(chanbuf(c, c.sendx))
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
}
- memmove(chanbuf(c, c.sendx), cas.elem, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, chanbuf(c, c.sendx), cas.elem)
c.sendx++
if c.sendx == c.dataqsiz {
c.sendx = 0
*cas.receivedp = true
}
if cas.elem != nil {
- memmove(cas.elem, sg.elem, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, cas.elem, sg.elem)
}
sg.elem = nil
gp = sg.g
print("syncsend: sel=", sel, " c=", c, "\n")
}
if sg.elem != nil {
- memmove(sg.elem, cas.elem, uintptr(c.elemsize))
+ typedmemmove(c.elemtype, sg.elem, cas.elem)
}
sg.elem = nil
gp = sg.g