var ret []Value
if nout == 0 {
+ // This is untyped because the frame is really a
+ // stack, even though it's a heap object.
memclr(args, frametype.size)
framePool.Put(args)
} else {
retOffset,
frametype.size-retOffset)
+ // This is untyped because the frame is really a stack, even
+ // though it's a heap object.
memclr(args, frametype.size)
framePool.Put(args)
}
break
}
if sg.elem != nil {
- memclr(sg.elem, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, sg.elem)
sg.elem = nil
}
if sg.releasetime != 0 {
}
unlock(&c.lock)
if ep != nil {
- memclr(ep, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, ep)
}
return true, false
}
if ep != nil {
typedmemmove(c.elemtype, ep, qp)
}
- memclr(qp, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, qp)
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx = 0
if !alg.equal(key, k2) {
continue
}
- memclr(k, uintptr(t.keysize))
+ if t.indirectkey {
+ *(*unsafe.Pointer)(k) = nil
+ } else {
+ typedmemclr(t.key, k)
+ }
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
- memclr(v, uintptr(t.valuesize))
+ if t.indirectvalue {
+ *(*unsafe.Pointer)(v) = nil
+ } else {
+ typedmemclr(t.elem, v)
+ }
b.tophash[i] = empty
h.count--
goto done
b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
// Preserve b.tophash because the evacuation
// state is maintained there.
- memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ if t.bucket.kind&kindNoPointers == 0 {
+ memclrHasPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ } else {
+ memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ }
}
}
func assertI2T2(t *_type, i iface, r unsafe.Pointer) bool {
tab := i.tab
if tab == nil || tab._type != t {
- memclr(r, t.size)
+ typedmemclr(t, r)
return false
}
if isDirectIface(t) {
GC()
}
if e._type != t {
- memclr(r, t.size)
+ typedmemclr(t, r)
return false
}
if isDirectIface(t) {
}
return typedslicecopy(elemType, dst, src)
}
+
+// typedmemclr clears the typed memory at ptr with type typ. The
+// memory at ptr must already be type-safe.
+//
+// If the caller knows that typ has pointers, it can alternatively
+// call memclrHasPointers.
+//
+//go:nosplit
+func typedmemclr(typ *_type, ptr unsafe.Pointer) {
+ memclr(ptr, typ.size)
+}
+
+// memclrHasPointers clears n bytes of typed memory starting at ptr.
+// The caller must ensure that the type of the object at ptr has
+// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
+// does not have to point to the start of the allocation.
+//
+//go:nosplit
+func memclrHasPointers(ptr unsafe.Pointer, n uintptr) {
+ memclr(ptr, n)
+}
if cas.elem != nil {
typedmemmove(c.elemtype, cas.elem, qp)
}
- memclr(qp, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, qp)
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx = 0
*cas.receivedp = false
}
if cas.elem != nil {
- memclr(cas.elem, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, cas.elem)
}
if raceenabled {
raceacquire(unsafe.Pointer(c))
}
// memclr clears n bytes starting at ptr.
+//
+// Usually you should use typedmemclr. memclr should be used only when
+// the caller knows that *ptr contains no heap pointers or to
+// initialize memory to a type-safe state when allocation reuses dead
+// memory.
+//
// in memclr_*.s
//go:noescape
func memclr(ptr unsafe.Pointer, n uintptr)