Commit 87e48c5a authored by Austin Clements's avatar Austin Clements

runtime, cmd/compile: rename memclr -> memclrNoHeapPointers

Since barrier-less memclr is only safe in very narrow circumstances,
this commit renames memclr to avoid accidentally calling memclr on
typed memory. This can cause subtle, non-deterministic bugs, so it's
worth some effort to prevent. In the near term, this will also prevent
bugs creeping in from any concurrent CLs that add calls to memclr; if
this happens, whichever patch hits master second will fail to compile.

This also adds the other new memclr variants to the compiler's
builtin.go to minimize the churn on that binary blob. We'll use these
in future commits.

Updates #17503.

Change-Id: I00eead049f5bd35ca107ea525966831f3d1ed9ca
Reviewed-on: https://go-review.googlesource.com/31369Reviewed-by: 's avatarKeith Randall <khr@golang.org>
Reviewed-by: 's avatarRick Hudson <rlh@golang.org>
parent ae3bb4a5
...@@ -87,51 +87,53 @@ var runtimeDecls = [...]struct { ...@@ -87,51 +87,53 @@ var runtimeDecls = [...]struct {
{"writeBarrier", varTag, 76}, {"writeBarrier", varTag, 76},
{"writebarrierptr", funcTag, 77}, {"writebarrierptr", funcTag, 77},
{"typedmemmove", funcTag, 78}, {"typedmemmove", funcTag, 78},
{"typedslicecopy", funcTag, 79}, {"typedmemclr", funcTag, 79},
{"selectnbsend", funcTag, 80}, {"typedslicecopy", funcTag, 80},
{"selectnbrecv", funcTag, 81}, {"selectnbsend", funcTag, 81},
{"selectnbrecv2", funcTag, 83}, {"selectnbrecv", funcTag, 82},
{"newselect", funcTag, 84}, {"selectnbrecv2", funcTag, 84},
{"selectsend", funcTag, 80}, {"newselect", funcTag, 85},
{"selectsend", funcTag, 81},
{"selectrecv", funcTag, 73}, {"selectrecv", funcTag, 73},
{"selectrecv2", funcTag, 85}, {"selectrecv2", funcTag, 86},
{"selectdefault", funcTag, 86}, {"selectdefault", funcTag, 87},
{"selectgo", funcTag, 87}, {"selectgo", funcTag, 88},
{"block", funcTag, 5}, {"block", funcTag, 5},
{"makeslice", funcTag, 89}, {"makeslice", funcTag, 90},
{"makeslice64", funcTag, 90}, {"makeslice64", funcTag, 91},
{"growslice", funcTag, 91}, {"growslice", funcTag, 92},
{"memmove", funcTag, 92}, {"memmove", funcTag, 93},
{"memclr", funcTag, 93}, {"memclrNoHeapPointers", funcTag, 94},
{"memequal", funcTag, 94}, {"memclrHasPointers", funcTag, 94},
{"memequal8", funcTag, 95}, {"memequal", funcTag, 95},
{"memequal16", funcTag, 95}, {"memequal8", funcTag, 96},
{"memequal32", funcTag, 95}, {"memequal16", funcTag, 96},
{"memequal64", funcTag, 95}, {"memequal32", funcTag, 96},
{"memequal128", funcTag, 95}, {"memequal64", funcTag, 96},
{"int64div", funcTag, 96}, {"memequal128", funcTag, 96},
{"uint64div", funcTag, 97}, {"int64div", funcTag, 97},
{"int64mod", funcTag, 96}, {"uint64div", funcTag, 98},
{"uint64mod", funcTag, 97}, {"int64mod", funcTag, 97},
{"float64toint64", funcTag, 98}, {"uint64mod", funcTag, 98},
{"float64touint64", funcTag, 99}, {"float64toint64", funcTag, 99},
{"float64touint32", funcTag, 101}, {"float64touint64", funcTag, 100},
{"int64tofloat64", funcTag, 102}, {"float64touint32", funcTag, 102},
{"uint64tofloat64", funcTag, 103}, {"int64tofloat64", funcTag, 103},
{"uint32tofloat64", funcTag, 104}, {"uint64tofloat64", funcTag, 104},
{"complex128div", funcTag, 105}, {"uint32tofloat64", funcTag, 105},
{"racefuncenter", funcTag, 106}, {"complex128div", funcTag, 106},
{"racefuncenter", funcTag, 107},
{"racefuncexit", funcTag, 5}, {"racefuncexit", funcTag, 5},
{"raceread", funcTag, 106}, {"raceread", funcTag, 107},
{"racewrite", funcTag, 106}, {"racewrite", funcTag, 107},
{"racereadrange", funcTag, 107}, {"racereadrange", funcTag, 108},
{"racewriterange", funcTag, 107}, {"racewriterange", funcTag, 108},
{"msanread", funcTag, 107}, {"msanread", funcTag, 108},
{"msanwrite", funcTag, 107}, {"msanwrite", funcTag, 108},
} }
func runtimeTypes() []*Type { func runtimeTypes() []*Type {
var typs [108]*Type var typs [109]*Type
typs[0] = bytetype typs[0] = bytetype
typs[1] = typPtr(typs[0]) typs[1] = typPtr(typs[0])
typs[2] = Types[TANY] typs[2] = Types[TANY]
...@@ -211,34 +213,35 @@ func runtimeTypes() []*Type { ...@@ -211,34 +213,35 @@ func runtimeTypes() []*Type {
typs[76] = tostruct([]*Node{namedfield("enabled", typs[13]), namedfield("needed", typs[13]), namedfield("cgo", typs[13])}) typs[76] = tostruct([]*Node{namedfield("enabled", typs[13]), namedfield("needed", typs[13]), namedfield("cgo", typs[13])})
typs[77] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil) typs[77] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[33])}) typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[13])}) typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[33])})
typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[71])}, []*Node{anonfield(typs[13])}) typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[13])})
typs[82] = typPtr(typs[13]) typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[71])}, []*Node{anonfield(typs[13])})
typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[82]), anonfield(typs[71])}, []*Node{anonfield(typs[13])}) typs[83] = typPtr(typs[13])
typs[84] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[17]), anonfield(typs[10])}, nil) typs[84] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[83]), anonfield(typs[71])}, []*Node{anonfield(typs[13])})
typs[85] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[71]), anonfield(typs[3]), anonfield(typs[82])}, []*Node{anonfield(typs[13])}) typs[85] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[17]), anonfield(typs[10])}, nil)
typs[86] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[13])}) typs[86] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[71]), anonfield(typs[3]), anonfield(typs[83])}, []*Node{anonfield(typs[13])})
typs[87] = functype(nil, []*Node{anonfield(typs[1])}, nil) typs[87] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[13])})
typs[88] = typSlice(typs[2]) typs[88] = functype(nil, []*Node{anonfield(typs[1])}, nil)
typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[33]), anonfield(typs[33])}, []*Node{anonfield(typs[88])}) typs[89] = typSlice(typs[2])
typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[88])}) typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[33]), anonfield(typs[33])}, []*Node{anonfield(typs[89])})
typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[88]), anonfield(typs[33])}, []*Node{anonfield(typs[88])}) typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[89])})
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, nil) typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[89]), anonfield(typs[33])}, []*Node{anonfield(typs[89])})
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[50])}, nil) typs[93] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, nil)
typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, []*Node{anonfield(typs[13])}) typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[50])}, nil)
typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[13])}) typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, []*Node{anonfield(typs[13])})
typs[96] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])}) typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[13])})
typs[97] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) typs[97] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
typs[98] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[17])}) typs[98] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
typs[99] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[19])}) typs[99] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[17])})
typs[100] = Types[TUINT32] typs[100] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[19])})
typs[101] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[100])}) typs[101] = Types[TUINT32]
typs[102] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[15])}) typs[102] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[101])})
typs[103] = functype(nil, []*Node{anonfield(typs[19])}, []*Node{anonfield(typs[15])}) typs[103] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[15])})
typs[104] = functype(nil, []*Node{anonfield(typs[100])}, []*Node{anonfield(typs[15])}) typs[104] = functype(nil, []*Node{anonfield(typs[19])}, []*Node{anonfield(typs[15])})
typs[105] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[21])}) typs[105] = functype(nil, []*Node{anonfield(typs[101])}, []*Node{anonfield(typs[15])})
typs[106] = functype(nil, []*Node{anonfield(typs[50])}, nil) typs[106] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[21])})
typs[107] = functype(nil, []*Node{anonfield(typs[50]), anonfield(typs[50])}, nil) typs[107] = functype(nil, []*Node{anonfield(typs[50])}, nil)
typs[108] = functype(nil, []*Node{anonfield(typs[50]), anonfield(typs[50])}, nil)
return typs[:] return typs[:]
} }
...@@ -113,6 +113,7 @@ func writebarrierptr(dst *any, src any) ...@@ -113,6 +113,7 @@ func writebarrierptr(dst *any, src any)
// *byte is really *runtime.Type // *byte is really *runtime.Type
func typedmemmove(typ *byte, dst *any, src *any) func typedmemmove(typ *byte, dst *any, src *any)
func typedmemclr(typ *byte, dst *any)
func typedslicecopy(typ *byte, dst any, src any) int func typedslicecopy(typ *byte, dst any, src any) int
func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
...@@ -131,7 +132,8 @@ func makeslice(typ *byte, len int, cap int) (ary []any) ...@@ -131,7 +132,8 @@ func makeslice(typ *byte, len int, cap int) (ary []any)
func makeslice64(typ *byte, len int64, cap int64) (ary []any) func makeslice64(typ *byte, len int64, cap int64) (ary []any)
func growslice(typ *byte, old []any, cap int) (ary []any) func growslice(typ *byte, old []any, cap int) (ary []any)
func memmove(to *any, frm *any, length uintptr) func memmove(to *any, frm *any, length uintptr)
func memclr(ptr *byte, length uintptr) func memclrNoHeapPointers(ptr *byte, length uintptr)
func memclrHasPointers(ptr *byte, length uintptr)
func memequal(x, y *any, size uintptr) bool func memequal(x, y *any, size uintptr) bool
func memequal8(x, y *any) bool func memequal8(x, y *any) bool
......
...@@ -393,11 +393,13 @@ func memclrrange(n, v1, v2, a *Node) bool { ...@@ -393,11 +393,13 @@ func memclrrange(n, v1, v2, a *Node) bool {
return false return false
} }
// TODO: Use memclrHasPointers if there are pointers.
// Convert to // Convert to
// if len(a) != 0 { // if len(a) != 0 {
// hp = &a[0] // hp = &a[0]
// hn = len(a)*sizeof(elem(a)) // hn = len(a)*sizeof(elem(a))
// memclr(hp, hn) // memclrNoHeapPointers(hp, hn)
// i = len(a) - 1 // i = len(a) - 1
// } // }
n.Op = OIF n.Op = OIF
...@@ -423,8 +425,8 @@ func memclrrange(n, v1, v2, a *Node) bool { ...@@ -423,8 +425,8 @@ func memclrrange(n, v1, v2, a *Node) bool {
tmp = conv(tmp, Types[TUINTPTR]) tmp = conv(tmp, Types[TUINTPTR])
n.Nbody.Append(nod(OAS, hn, tmp)) n.Nbody.Append(nod(OAS, hn, tmp))
// memclr(hp, hn) // memclrNoHeapPointers(hp, hn)
fn := mkcall("memclr", nil, nil, hp, hn) fn := mkcall("memclrNoHeapPointers", nil, nil, hp, hn)
n.Nbody.Append(fn) n.Nbody.Append(fn)
......
...@@ -442,13 +442,13 @@ func (v Value) call(op string, in []Value) []Value { ...@@ -442,13 +442,13 @@ func (v Value) call(op string, in []Value) []Value {
if nout == 0 { if nout == 0 {
// This is untyped because the frame is really a // This is untyped because the frame is really a
// stack, even though it's a heap object. // stack, even though it's a heap object.
memclr(args, frametype.size) memclrNoHeapPointers(args, frametype.size)
framePool.Put(args) framePool.Put(args)
} else { } else {
// Zero the now unused input area of args, // Zero the now unused input area of args,
// because the Values returned by this function contain pointers to the args object, // because the Values returned by this function contain pointers to the args object,
// and will thus keep the args object alive indefinitely. // and will thus keep the args object alive indefinitely.
memclr(args, retOffset) memclrNoHeapPointers(args, retOffset)
// Wrap Values around return values in args. // Wrap Values around return values in args.
ret = make([]Value, nout) ret = make([]Value, nout)
off = retOffset off = retOffset
...@@ -648,7 +648,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) { ...@@ -648,7 +648,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
// This is untyped because the frame is really a stack, even // This is untyped because the frame is really a stack, even
// though it's a heap object. // though it's a heap object.
memclr(args, frametype.size) memclrNoHeapPointers(args, frametype.size)
framePool.Put(args) framePool.Put(args)
} }
...@@ -2512,7 +2512,7 @@ func typedmemmovepartial(t *rtype, dst, src unsafe.Pointer, off, size uintptr) ...@@ -2512,7 +2512,7 @@ func typedmemmovepartial(t *rtype, dst, src unsafe.Pointer, off, size uintptr)
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
//go:noescape //go:noescape
func memclr(ptr unsafe.Pointer, n uintptr) func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
// Dummy annotation marking that the value x escapes, // Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that // for use in cases where the reflect code is so clever that
......
...@@ -275,12 +275,6 @@ func ifaceHash(i interface { ...@@ -275,12 +275,6 @@ func ifaceHash(i interface {
return algarray[alg_INTER].hash(noescape(unsafe.Pointer(&i)), seed) return algarray[alg_INTER].hash(noescape(unsafe.Pointer(&i)), seed)
} }
// Testing adapter for memclr
func memclrBytes(b []byte) {
s := (*slice)(unsafe.Pointer(&b))
memclr(s.array, uintptr(s.len))
}
const hashRandomBytes = sys.PtrSize / 4 * 64 const hashRandomBytes = sys.PtrSize / 4 * 64
// used in asm_{386,amd64}.s to seed the hash function // used in asm_{386,amd64}.s to seed the hash function
......
...@@ -484,7 +484,7 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 ...@@ -484,7 +484,7 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
MOVL 0, AX MOVL 0, AX
RET RET
TEXT runtime·memclr(SB),NOSPLIT,$0-8 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
MOVL ptr+0(FP), DI MOVL ptr+0(FP), DI
MOVL n+4(FP), CX MOVL n+4(FP), CX
MOVQ CX, BX MOVQ CX, BX
......
...@@ -155,7 +155,11 @@ var Int32Hash = int32Hash ...@@ -155,7 +155,11 @@ var Int32Hash = int32Hash
var Int64Hash = int64Hash var Int64Hash = int64Hash
var EfaceHash = efaceHash var EfaceHash = efaceHash
var IfaceHash = ifaceHash var IfaceHash = ifaceHash
var MemclrBytes = memclrBytes
func MemclrBytes(b []byte) {
s := (*slice)(unsafe.Pointer(&b))
memclrNoHeapPointers(s.array, uintptr(s.len))
}
var HashLoad = &hashLoad var HashLoad = &hashLoad
......
...@@ -1090,7 +1090,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -1090,7 +1090,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
if t.bucket.kind&kindNoPointers == 0 { if t.bucket.kind&kindNoPointers == 0 {
memclrHasPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset) memclrHasPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
} else { } else {
memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset) memclrNoHeapPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
} }
} }
} }
......
...@@ -631,7 +631,7 @@ func mdump() { ...@@ -631,7 +631,7 @@ func mdump() {
s.ensureSwept() s.ensureSwept()
} }
} }
memclr(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache)) memclrNoHeapPointers(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache))
dwrite(unsafe.Pointer(&dumphdr[0]), uintptr(len(dumphdr))) dwrite(unsafe.Pointer(&dumphdr[0]), uintptr(len(dumphdr)))
dumpparams() dumpparams()
dumpitabs() dumpitabs()
......
...@@ -682,7 +682,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { ...@@ -682,7 +682,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
} }
x = unsafe.Pointer(v) x = unsafe.Pointer(v)
if needzero && span.needzero != 0 { if needzero && span.needzero != 0 {
memclr(unsafe.Pointer(v), size) memclrNoHeapPointers(unsafe.Pointer(v), size)
} }
} }
} else { } else {
......
...@@ -333,14 +333,17 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int { ...@@ -333,14 +333,17 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
} }
// typedmemclr clears the typed memory at ptr with type typ. The // typedmemclr clears the typed memory at ptr with type typ. The
// memory at ptr must already be type-safe. // memory at ptr must already be initialized (and hence in type-safe
// state). If the memory is being initialized for the first time, see
// memclrNoHeapPointers.
// //
// If the caller knows that typ has pointers, it can alternatively // If the caller knows that typ has pointers, it can alternatively
// call memclrHasPointers. // call memclrHasPointers.
// //
//go:nosplit //go:nosplit
func typedmemclr(typ *_type, ptr unsafe.Pointer) { func typedmemclr(typ *_type, ptr unsafe.Pointer) {
memclr(ptr, typ.size) // TODO(austin): Call the hybrid barrier.
memclrNoHeapPointers(ptr, typ.size)
} }
// memclrHasPointers clears n bytes of typed memory starting at ptr. // memclrHasPointers clears n bytes of typed memory starting at ptr.
...@@ -350,5 +353,6 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) { ...@@ -350,5 +353,6 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
// //
//go:nosplit //go:nosplit
func memclrHasPointers(ptr unsafe.Pointer, n uintptr) { func memclrHasPointers(ptr unsafe.Pointer, n uintptr) {
memclr(ptr, n) // TODO(austin): Call the hybrid barrier.
memclrNoHeapPointers(ptr, n)
} }
...@@ -742,7 +742,7 @@ func (h heapBits) initSpan(s *mspan) { ...@@ -742,7 +742,7 @@ func (h heapBits) initSpan(s *mspan) {
} }
return return
} }
memclr(unsafe.Pointer(subtractb(h.bitp, nbyte-1)), nbyte) memclrNoHeapPointers(unsafe.Pointer(subtractb(h.bitp, nbyte-1)), nbyte)
} }
// initCheckmarkSpan initializes a span for being checkmarked. // initCheckmarkSpan initializes a span for being checkmarked.
...@@ -1433,7 +1433,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u ...@@ -1433,7 +1433,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
} }
endProg := unsafe.Pointer(subtractb(h.bitp, (totalBits+3)/4)) endProg := unsafe.Pointer(subtractb(h.bitp, (totalBits+3)/4))
endAlloc := unsafe.Pointer(subtractb(h.bitp, allocSize/heapBitmapScale)) endAlloc := unsafe.Pointer(subtractb(h.bitp, allocSize/heapBitmapScale))
memclr(add(endAlloc, 1), uintptr(endProg)-uintptr(endAlloc)) memclrNoHeapPointers(add(endAlloc, 1), uintptr(endProg)-uintptr(endAlloc))
} }
// progToPointerMask returns the 1-bit pointer mask output by the GC program prog. // progToPointerMask returns the 1-bit pointer mask output by the GC program prog.
......
...@@ -38,7 +38,7 @@ func memAlloc(n uintptr) unsafe.Pointer { ...@@ -38,7 +38,7 @@ func memAlloc(n uintptr) unsafe.Pointer {
p.size -= n p.size -= n
p = (*memHdr)(add(unsafe.Pointer(p), p.size)) p = (*memHdr)(add(unsafe.Pointer(p), p.size))
} }
memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})) *p = memHdr{}
return unsafe.Pointer(p) return unsafe.Pointer(p)
} }
prevp = p prevp = p
...@@ -48,7 +48,7 @@ func memAlloc(n uintptr) unsafe.Pointer { ...@@ -48,7 +48,7 @@ func memAlloc(n uintptr) unsafe.Pointer {
func memFree(ap unsafe.Pointer, n uintptr) { func memFree(ap unsafe.Pointer, n uintptr) {
n = memRound(n) n = memRound(n)
memclr(ap, n) memclrNoHeapPointers(ap, n)
bp := (*memHdr)(ap) bp := (*memHdr)(ap)
bp.size = n bp.size = n
bpn := uintptr(ap) bpn := uintptr(ap)
...@@ -63,7 +63,7 @@ func memFree(ap unsafe.Pointer, n uintptr) { ...@@ -63,7 +63,7 @@ func memFree(ap unsafe.Pointer, n uintptr) {
if bpn+bp.size == uintptr(unsafe.Pointer(p)) { if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
bp.size += p.size bp.size += p.size
bp.next = p.next bp.next = p.next
memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})) *p = memHdr{}
} else { } else {
bp.next.set(p) bp.next.set(p)
} }
...@@ -77,14 +77,14 @@ func memFree(ap unsafe.Pointer, n uintptr) { ...@@ -77,14 +77,14 @@ func memFree(ap unsafe.Pointer, n uintptr) {
if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) { if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
bp.size += p.next.ptr().size bp.size += p.next.ptr().size
bp.next = p.next.ptr().next bp.next = p.next.ptr().next
memclr(unsafe.Pointer(p.next), unsafe.Sizeof(memHdr{})) *p.next.ptr() = memHdr{}
} else { } else {
bp.next = p.next bp.next = p.next
} }
if uintptr(unsafe.Pointer(p))+p.size == bpn { if uintptr(unsafe.Pointer(p))+p.size == bpn {
p.size += bp.size p.size += bp.size
p.next = bp.next p.next = bp.next
memclr(unsafe.Pointer(bp), unsafe.Sizeof(memHdr{})) *bp = memHdr{}
} else { } else {
p.next.set(bp) p.next.set(bp)
} }
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
// NOTE: Windows externalthreadhandler expects memclr to preserve DX. // NOTE: Windows externalthreadhandler expects memclr to preserve DX.
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-8 TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
MOVL ptr+0(FP), DI MOVL ptr+0(FP), DI
MOVL n+4(FP), BX MOVL n+4(FP), BX
XORL AX, AX XORL AX, AX
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
// NOTE: Windows externalthreadhandler expects memclr to preserve DX. // NOTE: Windows externalthreadhandler expects memclr to preserve DX.
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-16 TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16
MOVQ ptr+0(FP), DI MOVQ ptr+0(FP), DI
MOVQ n+8(FP), BX MOVQ n+8(FP), BX
XORQ AX, AX XORQ AX, AX
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define N R12 #define N R12
#define TMP R12 /* N and TMP don't overlap */ #define TMP R12 /* N and TMP don't overlap */
TEXT runtime·memclr(SB),NOSPLIT,$0-8 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
MOVW ptr+0(FP), TO MOVW ptr+0(FP), TO
MOVW n+4(FP), N MOVW n+4(FP), N
MOVW $0, R0 MOVW $0, R0
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB),NOSPLIT,$0-16 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
MOVD ptr+0(FP), R3 MOVD ptr+0(FP), R3
MOVD n+8(FP), R4 MOVD n+8(FP), R4
// TODO(mwhudson): this is written this way to avoid tickling // TODO(mwhudson): this is written this way to avoid tickling
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB),NOSPLIT,$0-16 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
MOVV ptr+0(FP), R1 MOVV ptr+0(FP), R1
MOVV n+8(FP), R2 MOVV n+8(FP), R2
ADDV R1, R2, R4 ADDV R1, R2, R4
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT, $0-8 TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
MOVL ptr+0(FP), DI MOVL ptr+0(FP), DI
MOVL n+4(FP), BX MOVL n+4(FP), BX
XORL AX, AX XORL AX, AX
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB),NOSPLIT,$0-16 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
MOVQ ptr+0(FP), DI MOVQ ptr+0(FP), DI
MOVQ n+8(FP), CX MOVQ n+8(FP), CX
MOVQ CX, BX MOVQ CX, BX
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB), NOSPLIT|NOFRAME, $0-16 TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT|NOFRAME, $0-16
MOVD ptr+0(FP), R3 MOVD ptr+0(FP), R3
MOVD n+8(FP), R4 MOVD n+8(FP), R4
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include "textflag.h" #include "textflag.h"
// void runtime·memclr(void*, uintptr) // void runtime·memclrNoHeapPointers(void*, uintptr)
TEXT runtime·memclr(SB),NOSPLIT|NOFRAME,$0-16 TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT|NOFRAME,$0-16
MOVD ptr+0(FP), R4 MOVD ptr+0(FP), R4
MOVD n+8(FP), R5 MOVD n+8(FP), R5
......
...@@ -72,7 +72,7 @@ func (f *fixalloc) alloc() unsafe.Pointer { ...@@ -72,7 +72,7 @@ func (f *fixalloc) alloc() unsafe.Pointer {
f.list = f.list.next f.list = f.list.next
f.inuse += f.size f.inuse += f.size
if f.zero { if f.zero {
memclr(v, f.size) memclrNoHeapPointers(v, f.size)
} }
return v return v
} }
......
...@@ -629,7 +629,7 @@ func (h *mheap) alloc(npage uintptr, sizeclass int32, large bool, needzero bool) ...@@ -629,7 +629,7 @@ func (h *mheap) alloc(npage uintptr, sizeclass int32, large bool, needzero bool)
if s != nil { if s != nil {
if needzero && s.needzero != 0 { if needzero && s.needzero != 0 {
memclr(unsafe.Pointer(s.base()), s.npages<<_PageShift) memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift)
} }
s.needzero = 0 s.needzero = 0
} }
...@@ -1418,7 +1418,7 @@ func newArena() *gcBits { ...@@ -1418,7 +1418,7 @@ func newArena() *gcBits {
} else { } else {
result = gcBitsArenas.free result = gcBitsArenas.free
gcBitsArenas.free = gcBitsArenas.free.next gcBitsArenas.free = gcBitsArenas.free.next
memclr(unsafe.Pointer(result), gcBitsChunkBytes) memclrNoHeapPointers(unsafe.Pointer(result), gcBitsChunkBytes)
} }
result.next = nil result.next = nil
// If result.bits is not 8 byte aligned adjust index so // If result.bits is not 8 byte aligned adjust index so
......
...@@ -317,7 +317,7 @@ func semacreate(mp *m) { ...@@ -317,7 +317,7 @@ func semacreate(mp *m) {
// here because it could cause a deadlock. // here because it could cause a deadlock.
_g_.m.libcall.fn = uintptr(unsafe.Pointer(&libc_malloc)) _g_.m.libcall.fn = uintptr(unsafe.Pointer(&libc_malloc))
_g_.m.libcall.n = 1 _g_.m.libcall.n = 1
memclr(unsafe.Pointer(&_g_.m.scratch), uintptr(len(_g_.m.scratch.v))) _g_.m.scratch = mscratch{}
_g_.m.scratch.v[0] = unsafe.Sizeof(*sem) _g_.m.scratch.v[0] = unsafe.Sizeof(*sem)
_g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch)) _g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall))
...@@ -337,7 +337,7 @@ func semasleep(ns int64) int32 { ...@@ -337,7 +337,7 @@ func semasleep(ns int64) int32 {
_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np)) _m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np))
_m_.libcall.n = 2 _m_.libcall.n = 2
memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) _m_.scratch = mscratch{}
_m_.scratch.v[0] = _m_.waitsema _m_.scratch.v[0] = _m_.waitsema
_m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts)) _m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts))
_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
...@@ -353,7 +353,7 @@ func semasleep(ns int64) int32 { ...@@ -353,7 +353,7 @@ func semasleep(ns int64) int32 {
for { for {
_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait)) _m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait))
_m_.libcall.n = 1 _m_.libcall.n = 1
memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) _m_.scratch = mscratch{}
_m_.scratch.v[0] = _m_.waitsema _m_.scratch.v[0] = _m_.waitsema
_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
......
...@@ -2812,7 +2812,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr ...@@ -2812,7 +2812,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr
} }
memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg)) memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched)) memclrNoHeapPointers(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
newg.sched.sp = sp newg.sched.sp = sp
newg.stktopsp = sp newg.stktopsp = sp
newg.sched.pc = funcPC(goexit) + sys.PCQuantum // +PCQuantum so that previous instruction is in same function newg.sched.pc = funcPC(goexit) + sys.PCQuantum // +PCQuantum so that previous instruction is in same function
......
...@@ -141,7 +141,7 @@ func growslice(et *_type, old slice, cap int) slice { ...@@ -141,7 +141,7 @@ func growslice(et *_type, old slice, cap int) slice {
memmove(p, old.array, lenmem) memmove(p, old.array, lenmem)
// The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length). // The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
// Only clear the part that will not be overwritten. // Only clear the part that will not be overwritten.
memclr(add(p, newlenmem), capmem-newlenmem) memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
} else { } else {
// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory. // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
p = mallocgc(capmem, et, true) p = mallocgc(capmem, et, true)
......
...@@ -436,7 +436,7 @@ func stackfree(stk stack, n uintptr) { ...@@ -436,7 +436,7 @@ func stackfree(stk stack, n uintptr) {
} }
if stackDebug >= 1 { if stackDebug >= 1 {
println("stackfree", v, n) println("stackfree", v, n)
memclr(v, n) // for testing, clobber stack data memclrNoHeapPointers(v, n) // for testing, clobber stack data
} }
if debug.efence != 0 || stackFromSystem != 0 { if debug.efence != 0 || stackFromSystem != 0 {
if debug.efence != 0 || stackFaultOnFree != 0 { if debug.efence != 0 || stackFaultOnFree != 0 {
......
...@@ -249,7 +249,7 @@ func rawbyteslice(size int) (b []byte) { ...@@ -249,7 +249,7 @@ func rawbyteslice(size int) (b []byte) {
cap := roundupsize(uintptr(size)) cap := roundupsize(uintptr(size))
p := mallocgc(cap, nil, false) p := mallocgc(cap, nil, false)
if cap != uintptr(size) { if cap != uintptr(size) {
memclr(add(p, uintptr(size)), cap-uintptr(size)) memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
} }
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)} *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
...@@ -264,7 +264,7 @@ func rawruneslice(size int) (b []rune) { ...@@ -264,7 +264,7 @@ func rawruneslice(size int) (b []rune) {
mem := roundupsize(uintptr(size) * 4) mem := roundupsize(uintptr(size) * 4)
p := mallocgc(mem, nil, false) p := mallocgc(mem, nil, false)
if mem != uintptr(size)*4 { if mem != uintptr(size)*4 {
memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4) memclrNoHeapPointers(add(p, uintptr(size)*4), mem-uintptr(size)*4)
} }
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)} *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)}
......
...@@ -60,20 +60,24 @@ func badsystemstack() { ...@@ -60,20 +60,24 @@ func badsystemstack() {
throw("systemstack called from unexpected goroutine") throw("systemstack called from unexpected goroutine")
} }
// memclr clears n bytes starting at ptr. // memclrNoHeapPointers clears n bytes starting at ptr.
// //
// Usually you should use typedmemclr. memclr should be used only when // Usually you should use typedmemclr. memclrNoHeapPointers should be
// the caller knows that *ptr contains no heap pointers or to // used only when the caller knows that *ptr contains no heap pointers
// initialize memory to a type-safe state when allocation reuses dead // because either:
// memory. //
// 1. *ptr is initialized memory and its type is pointer-free.
//
// 2. *ptr is uninitialized memory (e.g., memory that's being reused
// for a new allocation) and hence contains only "junk".
// //
// in memclr_*.s // in memclr_*.s
//go:noescape //go:noescape
func memclr(ptr unsafe.Pointer, n uintptr) func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
//go:linkname reflect_memclr reflect.memclr //go:linkname reflect_memclrNoHeapPointers reflect.memclrNoHeapPointers
func reflect_memclr(ptr unsafe.Pointer, n uintptr) { func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) {
memclr(ptr, n) memclrNoHeapPointers(ptr, n)
} }
// memmove copies n bytes from "from" to "to". // memmove copies n bytes from "from" to "to".
......
...@@ -192,7 +192,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 ...@@ -192,7 +192,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
SUBL $m__size, SP // space for M SUBL $m__size, SP // space for M
MOVL SP, 0(SP) MOVL SP, 0(SP)
MOVL $m__size, 4(SP) MOVL $m__size, 4(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX
LEAL m_tls(SP), CX LEAL m_tls(SP), CX
MOVL CX, 0x14(FS) MOVL CX, 0x14(FS)
...@@ -203,7 +203,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 ...@@ -203,7 +203,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
MOVL SP, 0(SP) MOVL SP, 0(SP)
MOVL $g__size, 4(SP) MOVL $g__size, 4(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX
LEAL g__size(SP), BX LEAL g__size(SP), BX
MOVL BX, g_m(SP) MOVL BX, g_m(SP)
......
...@@ -236,7 +236,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0 ...@@ -236,7 +236,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
SUBQ $m__size, SP // space for M SUBQ $m__size, SP // space for M
MOVQ SP, 0(SP) MOVQ SP, 0(SP)
MOVQ $m__size, 8(SP) MOVQ $m__size, 8(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX, maybe BP CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX, maybe BP
LEAQ m_tls(SP), CX LEAQ m_tls(SP), CX
MOVQ CX, 0x28(GS) MOVQ CX, 0x28(GS)
...@@ -247,7 +247,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0 ...@@ -247,7 +247,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
MOVQ SP, 0(SP) MOVQ SP, 0(SP)
MOVQ $g__size, 8(SP) MOVQ $g__size, 8(SP)
CALL runtime·memclr(SB) // smashes AX,BX,CX, maybe BP CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX, maybe BP
LEAQ g__size(SP), BX LEAQ g__size(SP), BX
MOVQ BX, g_m(SP) MOVQ BX, g_m(SP)
......
...@@ -75,7 +75,9 @@ func writeErr(b []byte) { ...@@ -75,7 +75,9 @@ func writeErr(b []byte) {
if v == '\n' || writePos == len(dst)-1 { if v == '\n' || writePos == len(dst)-1 {
dst[writePos] = 0 dst[writePos] = 0
write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos)) write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
memclrBytes(dst) for i := range dst {
dst[i] = 0
}
writePos = 0 writePos = 0
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment