Commit db16de92 authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

runtime: remove kindNoPointers

We already have the ptrdata field in a type, which encodes exactly
the same information that kindNoPointers does.

My problem with kindNoPointers is that it often leads to
double-negative code like:

   t.kind & kindNoPointers != 0

Much clearer is:

   t.ptrdata == 0

Update #27167

Change-Id: I92307d7f018a6bbe3daca4a4abb4225e359349b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/169157
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 50163233
...@@ -882,9 +882,6 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { ...@@ -882,9 +882,6 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
ot = duint8(lsym, ot, t.Align) // fieldAlign ot = duint8(lsym, ot, t.Align) // fieldAlign
i = kinds[t.Etype] i = kinds[t.Etype]
if !types.Haspointers(t) {
i |= objabi.KindNoPointers
}
if isdirectiface(t) { if isdirectiface(t) {
i |= objabi.KindDirectIface i |= objabi.KindDirectIface
} }
......
...@@ -36,6 +36,5 @@ const ( ...@@ -36,6 +36,5 @@ const (
KindUnsafePointer KindUnsafePointer
KindDirectIface = 1 << 5 KindDirectIface = 1 << 5
KindGCProg = 1 << 6 KindGCProg = 1 << 6
KindNoPointers = 1 << 7
KindMask = (1 << 5) - 1 KindMask = (1 << 5) - 1
) )
...@@ -370,7 +370,6 @@ func (n name) pkgPath() string { ...@@ -370,7 +370,6 @@ func (n name) pkgPath() string {
const ( const (
kindDirectIface = 1 << 5 kindDirectIface = 1 << 5
kindGCProg = 1 << 6 // Type.gc points to GC program kindGCProg = 1 << 6 // Type.gc points to GC program
kindNoPointers = 1 << 7
kindMask = (1 << 5) - 1 kindMask = (1 << 5) - 1
) )
......
...@@ -40,7 +40,7 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, ...@@ -40,7 +40,7 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr,
for i := uintptr(0); i < ft.ptrdata/ptrSize; i++ { for i := uintptr(0); i < ft.ptrdata/ptrSize; i++ {
gc = append(gc, gcdata[i/8]>>(i%8)&1) gc = append(gc, gcdata[i/8]>>(i%8)&1)
} }
ptrs = ft.kind&kindNoPointers == 0 ptrs = ft.ptrdata != 0
return return
} }
......
...@@ -29,7 +29,7 @@ func Swapper(slice interface{}) func(i, j int) { ...@@ -29,7 +29,7 @@ func Swapper(slice interface{}) func(i, j int) {
typ := v.Type().Elem().(*rtype) typ := v.Type().Elem().(*rtype)
size := typ.Size() size := typ.Size()
hasPtr := typ.kind&kindNoPointers == 0 hasPtr := typ.ptrdata != 0
// Some common & small cases, without using memmove: // Some common & small cases, without using memmove:
if hasPtr { if hasPtr {
......
...@@ -586,7 +586,6 @@ type Method struct { ...@@ -586,7 +586,6 @@ type Method struct {
const ( const (
kindDirectIface = 1 << 5 kindDirectIface = 1 << 5
kindGCProg = 1 << 6 // Type.gc points to GC program kindGCProg = 1 << 6 // Type.gc points to GC program
kindNoPointers = 1 << 7
kindMask = (1 << 5) - 1 kindMask = (1 << 5) - 1
) )
...@@ -782,7 +781,7 @@ func (t *rtype) FieldAlign() int { return int(t.fieldAlign) } ...@@ -782,7 +781,7 @@ func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 } func (t *rtype) pointers() bool { return t.ptrdata != 0 }
func (t *rtype) common() *rtype { return t } func (t *rtype) common() *rtype { return t }
...@@ -2156,13 +2155,6 @@ const ( ...@@ -2156,13 +2155,6 @@ const (
) )
func bucketOf(ktyp, etyp *rtype) *rtype { func bucketOf(ktyp, etyp *rtype) *rtype {
// See comment on hmap.overflow in ../runtime/map.go.
var kind uint8
if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 &&
ktyp.size <= maxKeySize && etyp.size <= maxValSize {
kind = kindNoPointers
}
if ktyp.size > maxKeySize { if ktyp.size > maxKeySize {
ktyp = PtrTo(ktyp).(*rtype) ktyp = PtrTo(ktyp).(*rtype)
} }
...@@ -2189,12 +2181,12 @@ func bucketOf(ktyp, etyp *rtype) *rtype { ...@@ -2189,12 +2181,12 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
panic("reflect: bad size computation in MapOf") panic("reflect: bad size computation in MapOf")
} }
if kind != kindNoPointers { if ktyp.ptrdata != 0 || etyp.ptrdata != 0 {
nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize
mask := make([]byte, (nptr+7)/8) mask := make([]byte, (nptr+7)/8)
base := bucketSize / ptrSize base := bucketSize / ptrSize
if ktyp.kind&kindNoPointers == 0 { if ktyp.ptrdata != 0 {
if ktyp.kind&kindGCProg != 0 { if ktyp.kind&kindGCProg != 0 {
panic("reflect: unexpected GC program in MapOf") panic("reflect: unexpected GC program in MapOf")
} }
...@@ -2210,7 +2202,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { ...@@ -2210,7 +2202,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
} }
base += bucketSize * ktyp.size / ptrSize base += bucketSize * ktyp.size / ptrSize
if etyp.kind&kindNoPointers == 0 { if etyp.ptrdata != 0 {
if etyp.kind&kindGCProg != 0 { if etyp.kind&kindGCProg != 0 {
panic("reflect: unexpected GC program in MapOf") panic("reflect: unexpected GC program in MapOf")
} }
...@@ -2241,7 +2233,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { ...@@ -2241,7 +2233,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
b := &rtype{ b := &rtype{
align: ptrSize, align: ptrSize,
size: size, size: size,
kind: kind, kind: uint8(Struct),
ptrdata: ptrdata, ptrdata: ptrdata,
gcdata: gcdata, gcdata: gcdata,
} }
...@@ -2349,7 +2341,6 @@ func StructOf(fields []StructField) Type { ...@@ -2349,7 +2341,6 @@ func StructOf(fields []StructField) Type {
repr = make([]byte, 0, 64) repr = make([]byte, 0, 64)
fset = map[string]struct{}{} // fields' names fset = map[string]struct{}{} // fields' names
hasPtr = false // records whether at least one struct-field is a pointer
hasGCProg = false // records whether a struct-field type has a GCProg hasGCProg = false // records whether a struct-field type has a GCProg
) )
...@@ -2370,9 +2361,6 @@ func StructOf(fields []StructField) Type { ...@@ -2370,9 +2361,6 @@ func StructOf(fields []StructField) Type {
if ft.kind&kindGCProg != 0 { if ft.kind&kindGCProg != 0 {
hasGCProg = true hasGCProg = true
} }
if ft.pointers() {
hasPtr = true
}
// Update string and hash // Update string and hash
name := f.name.name() name := f.name.name()
...@@ -2657,11 +2645,6 @@ func StructOf(fields []StructField) Type { ...@@ -2657,11 +2645,6 @@ func StructOf(fields []StructField) Type {
if len(methods) > 0 { if len(methods) > 0 {
typ.tflag |= tflagUncommon typ.tflag |= tflagUncommon
} }
if !hasPtr {
typ.kind |= kindNoPointers
} else {
typ.kind &^= kindNoPointers
}
if hasGCProg { if hasGCProg {
lastPtrField := 0 lastPtrField := 0
...@@ -2869,11 +2852,9 @@ func ArrayOf(count int, elem Type) Type { ...@@ -2869,11 +2852,9 @@ func ArrayOf(count int, elem Type) Type {
array.len = uintptr(count) array.len = uintptr(count)
array.slice = SliceOf(elem).(*rtype) array.slice = SliceOf(elem).(*rtype)
array.kind &^= kindNoPointers
switch { switch {
case typ.kind&kindNoPointers != 0 || array.size == 0: case typ.ptrdata == 0 || array.size == 0:
// No pointers. // No pointers.
array.kind |= kindNoPointers
array.gcdata = nil array.gcdata = nil
array.ptrdata = 0 array.ptrdata = 0
...@@ -3087,8 +3068,6 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset ...@@ -3087,8 +3068,6 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset
} }
if ptrmap.n > 0 { if ptrmap.n > 0 {
x.gcdata = &ptrmap.data[0] x.gcdata = &ptrmap.data[0]
} else {
x.kind |= kindNoPointers
} }
var s string var s string
...@@ -3135,7 +3114,7 @@ func (bv *bitVector) append(bit uint8) { ...@@ -3135,7 +3114,7 @@ func (bv *bitVector) append(bit uint8) {
} }
func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
if t.kind&kindNoPointers != 0 { if t.ptrdata == 0 {
return return
} }
......
...@@ -460,7 +460,7 @@ const cgoResultFail = "cgo result has Go pointer" ...@@ -460,7 +460,7 @@ const cgoResultFail = "cgo result has Go pointer"
// depending on indir. The top parameter is whether we are at the top // depending on indir. The top parameter is whether we are at the top
// level, where Go pointers are allowed. // level, where Go pointers are allowed.
func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
if t.kind&kindNoPointers != 0 { if t.ptrdata == 0 {
// If the type has no pointers there is nothing to do. // If the type has no pointers there is nothing to do.
return return
} }
...@@ -523,7 +523,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { ...@@ -523,7 +523,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
if !top { if !top {
panic(errorString(msg)) panic(errorString(msg))
} }
if st.elem.kind&kindNoPointers != 0 { if st.elem.ptrdata == 0 {
return return
} }
for i := 0; i < s.cap; i++ { for i := 0; i < s.cap; i++ {
......
...@@ -64,7 +64,7 @@ func cgoCheckWriteBarrier(dst *uintptr, src uintptr) { ...@@ -64,7 +64,7 @@ func cgoCheckWriteBarrier(dst *uintptr, src uintptr) {
//go:nosplit //go:nosplit
//go:nowritebarrier //go:nowritebarrier
func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) { func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
if typ.kind&kindNoPointers != 0 { if typ.ptrdata == 0 {
return return
} }
if !cgoIsGoPointer(src) { if !cgoIsGoPointer(src) {
...@@ -83,7 +83,7 @@ func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) { ...@@ -83,7 +83,7 @@ func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
//go:nosplit //go:nosplit
//go:nowritebarrier //go:nowritebarrier
func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) { func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
if typ.kind&kindNoPointers != 0 { if typ.ptrdata == 0 {
return return
} }
if !cgoIsGoPointer(src.array) { if !cgoIsGoPointer(src.array) {
...@@ -203,7 +203,7 @@ func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) { ...@@ -203,7 +203,7 @@ func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) {
//go:nowritebarrier //go:nowritebarrier
//go:systemstack //go:systemstack
func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) { func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
if typ.kind&kindNoPointers != 0 { if typ.ptrdata == 0 {
return return
} }
......
...@@ -95,7 +95,7 @@ func makechan(t *chantype, size int) *hchan { ...@@ -95,7 +95,7 @@ func makechan(t *chantype, size int) *hchan {
c = (*hchan)(mallocgc(hchanSize, nil, true)) c = (*hchan)(mallocgc(hchanSize, nil, true))
// Race detector uses this location for synchronization. // Race detector uses this location for synchronization.
c.buf = c.raceaddr() c.buf = c.raceaddr()
case elem.kind&kindNoPointers != 0: case elem.ptrdata == 0:
// Elements do not contain pointers. // Elements do not contain pointers.
// Allocate hchan and buf in one call. // Allocate hchan and buf in one call.
c = (*hchan)(mallocgc(hchanSize+mem, nil, true)) c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
......
...@@ -195,7 +195,7 @@ func dumptype(t *_type) { ...@@ -195,7 +195,7 @@ func dumptype(t *_type) {
dwritebyte('.') dwritebyte('.')
dwrite(name.str, uintptr(name.len)) dwrite(name.str, uintptr(name.len))
} }
dumpbool(t.kind&kindDirectIface == 0 || t.kind&kindNoPointers == 0) dumpbool(t.kind&kindDirectIface == 0 || t.ptrdata != 0)
} }
// dump an object // dump an object
......
...@@ -858,7 +858,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { ...@@ -858,7 +858,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
dataSize := size dataSize := size
c := gomcache() c := gomcache()
var x unsafe.Pointer var x unsafe.Pointer
noscan := typ == nil || typ.kind&kindNoPointers != 0 noscan := typ == nil || typ.ptrdata == 0
if size <= maxSmallSize { if size <= maxSmallSize {
if noscan && size < maxTinySize { if noscan && size < maxTinySize {
// Tiny allocator. // Tiny allocator.
......
...@@ -264,7 +264,7 @@ func (h *hmap) newoverflow(t *maptype, b *bmap) *bmap { ...@@ -264,7 +264,7 @@ func (h *hmap) newoverflow(t *maptype, b *bmap) *bmap {
ovf = (*bmap)(newobject(t.bucket)) ovf = (*bmap)(newobject(t.bucket))
} }
h.incrnoverflow() h.incrnoverflow()
if t.bucket.kind&kindNoPointers != 0 { if t.bucket.ptrdata == 0 {
h.createOverflow() h.createOverflow()
*h.extra.overflow = append(*h.extra.overflow, ovf) *h.extra.overflow = append(*h.extra.overflow, ovf)
} }
...@@ -368,7 +368,7 @@ func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets un ...@@ -368,7 +368,7 @@ func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets un
// but may not be empty. // but may not be empty.
buckets = dirtyalloc buckets = dirtyalloc
size := t.bucket.size * nbuckets size := t.bucket.size * nbuckets
if t.bucket.kind&kindNoPointers == 0 { if t.bucket.ptrdata != 0 {
memclrHasPointers(buckets, size) memclrHasPointers(buckets, size)
} else { } else {
memclrNoHeapPointers(buckets, size) memclrNoHeapPointers(buckets, size)
...@@ -742,13 +742,13 @@ search: ...@@ -742,13 +742,13 @@ search:
// Only clear key if there are pointers in it. // Only clear key if there are pointers in it.
if t.indirectkey() { if t.indirectkey() {
*(*unsafe.Pointer)(k) = nil *(*unsafe.Pointer)(k) = nil
} else if t.key.kind&kindNoPointers == 0 { } else if t.key.ptrdata != 0 {
memclrHasPointers(k, t.key.size) memclrHasPointers(k, t.key.size)
} }
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize)) v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
if t.indirectvalue() { if t.indirectvalue() {
*(*unsafe.Pointer)(v) = nil *(*unsafe.Pointer)(v) = nil
} else if t.elem.kind&kindNoPointers == 0 { } else if t.elem.ptrdata != 0 {
memclrHasPointers(v, t.elem.size) memclrHasPointers(v, t.elem.size)
} else { } else {
memclrNoHeapPointers(v, t.elem.size) memclrNoHeapPointers(v, t.elem.size)
...@@ -820,7 +820,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { ...@@ -820,7 +820,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
// grab snapshot of bucket state // grab snapshot of bucket state
it.B = h.B it.B = h.B
it.buckets = h.buckets it.buckets = h.buckets
if t.bucket.kind&kindNoPointers != 0 { if t.bucket.ptrdata == 0 {
// Allocate the current slice and remember pointers to both current and old. // Allocate the current slice and remember pointers to both current and old.
// This preserves all relevant overflow buckets alive even if // This preserves all relevant overflow buckets alive even if
// the table grows and/or overflow buckets are added to the table // the table grows and/or overflow buckets are added to the table
...@@ -1232,7 +1232,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -1232,7 +1232,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
} }
} }
// Unlink the overflow buckets & clear key/value to help GC. // Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 && t.bucket.kind&kindNoPointers == 0 { if h.flags&oldIterator == 0 && t.bucket.ptrdata != 0 {
b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)) b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
// Preserve b.tophash because the evacuation // Preserve b.tophash because the evacuation
// state is maintained there. // state is maintained there.
......
...@@ -299,11 +299,11 @@ search: ...@@ -299,11 +299,11 @@ search:
continue continue
} }
// Only clear key if there are pointers in it. // Only clear key if there are pointers in it.
if t.key.kind&kindNoPointers == 0 { if t.key.ptrdata != 0 {
memclrHasPointers(k, t.key.size) memclrHasPointers(k, t.key.size)
} }
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize)) v := add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
if t.elem.kind&kindNoPointers == 0 { if t.elem.ptrdata != 0 {
memclrHasPointers(v, t.elem.size) memclrHasPointers(v, t.elem.size)
} else { } else {
memclrNoHeapPointers(v, t.elem.size) memclrNoHeapPointers(v, t.elem.size)
...@@ -418,7 +418,7 @@ func evacuate_fast32(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -418,7 +418,7 @@ func evacuate_fast32(t *maptype, h *hmap, oldbucket uintptr) {
dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check
// Copy key. // Copy key.
if sys.PtrSize == 4 && t.key.kind&kindNoPointers == 0 && writeBarrier.enabled { if sys.PtrSize == 4 && t.key.ptrdata != 0 && writeBarrier.enabled {
// Write with a write barrier. // Write with a write barrier.
*(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k) *(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k)
} else { } else {
...@@ -436,7 +436,7 @@ func evacuate_fast32(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -436,7 +436,7 @@ func evacuate_fast32(t *maptype, h *hmap, oldbucket uintptr) {
} }
} }
// Unlink the overflow buckets & clear key/value to help GC. // Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 && t.bucket.kind&kindNoPointers == 0 { if h.flags&oldIterator == 0 && t.bucket.ptrdata != 0 {
b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)) b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
// Preserve b.tophash because the evacuation // Preserve b.tophash because the evacuation
// state is maintained there. // state is maintained there.
......
...@@ -299,11 +299,11 @@ search: ...@@ -299,11 +299,11 @@ search:
continue continue
} }
// Only clear key if there are pointers in it. // Only clear key if there are pointers in it.
if t.key.kind&kindNoPointers == 0 { if t.key.ptrdata != 0 {
memclrHasPointers(k, t.key.size) memclrHasPointers(k, t.key.size)
} }
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize)) v := add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
if t.elem.kind&kindNoPointers == 0 { if t.elem.ptrdata != 0 {
memclrHasPointers(v, t.elem.size) memclrHasPointers(v, t.elem.size)
} else { } else {
memclrNoHeapPointers(v, t.elem.size) memclrNoHeapPointers(v, t.elem.size)
...@@ -418,7 +418,7 @@ func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -418,7 +418,7 @@ func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) {
dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check
// Copy key. // Copy key.
if t.key.kind&kindNoPointers == 0 && writeBarrier.enabled { if t.key.ptrdata != 0 && writeBarrier.enabled {
if sys.PtrSize == 8 { if sys.PtrSize == 8 {
// Write with a write barrier. // Write with a write barrier.
*(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k) *(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k)
...@@ -442,7 +442,7 @@ func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -442,7 +442,7 @@ func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) {
} }
} }
// Unlink the overflow buckets & clear key/value to help GC. // Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 && t.bucket.kind&kindNoPointers == 0 { if h.flags&oldIterator == 0 && t.bucket.ptrdata != 0 {
b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)) b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
// Preserve b.tophash because the evacuation // Preserve b.tophash because the evacuation
// state is maintained there. // state is maintained there.
......
...@@ -332,7 +332,7 @@ search: ...@@ -332,7 +332,7 @@ search:
// Clear key's pointer. // Clear key's pointer.
k.str = nil k.str = nil
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)) v := add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
if t.elem.kind&kindNoPointers == 0 { if t.elem.ptrdata != 0 {
memclrHasPointers(v, t.elem.size) memclrHasPointers(v, t.elem.size)
} else { } else {
memclrNoHeapPointers(v, t.elem.size) memclrNoHeapPointers(v, t.elem.size)
...@@ -461,7 +461,7 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) { ...@@ -461,7 +461,7 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) {
} }
// Unlink the overflow buckets & clear key/value to help GC. // Unlink the overflow buckets & clear key/value to help GC.
// Unlink the overflow buckets & clear key/value to help GC. // Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 && t.bucket.kind&kindNoPointers == 0 { if h.flags&oldIterator == 0 && t.bucket.ptrdata != 0 {
b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)) b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
// Preserve b.tophash because the evacuation // Preserve b.tophash because the evacuation
// state is maintained there. // state is maintained there.
......
...@@ -157,7 +157,7 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) { ...@@ -157,7 +157,7 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
if dst == src { if dst == src {
return return
} }
if typ.kind&kindNoPointers == 0 { if typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(dst), uintptr(src), typ.size) bulkBarrierPreWrite(uintptr(dst), uintptr(src), typ.size)
} }
// There's a race here: if some other goroutine can write to // There's a race here: if some other goroutine can write to
...@@ -195,7 +195,7 @@ func reflectlite_typedmemmove(typ *_type, dst, src unsafe.Pointer) { ...@@ -195,7 +195,7 @@ func reflectlite_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
// dst and src point off bytes into the value and only copies size bytes. // dst and src point off bytes into the value and only copies size bytes.
//go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial //go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial
func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) { func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
if writeBarrier.needed && typ.kind&kindNoPointers == 0 && size >= sys.PtrSize { if writeBarrier.needed && typ.ptrdata != 0 && size >= sys.PtrSize {
// Pointer-align start address for bulk barrier. // Pointer-align start address for bulk barrier.
adst, asrc, asize := dst, src, size adst, asrc, asize := dst, src, size
if frag := -off & (sys.PtrSize - 1); frag != 0 { if frag := -off & (sys.PtrSize - 1); frag != 0 {
...@@ -223,7 +223,7 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size ...@@ -223,7 +223,7 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size
// //
//go:nosplit //go:nosplit
func reflectcallmove(typ *_type, dst, src unsafe.Pointer, size uintptr) { func reflectcallmove(typ *_type, dst, src unsafe.Pointer, size uintptr) {
if writeBarrier.needed && typ != nil && typ.kind&kindNoPointers == 0 && size >= sys.PtrSize { if writeBarrier.needed && typ != nil && typ.ptrdata != 0 && size >= sys.PtrSize {
bulkBarrierPreWrite(uintptr(dst), uintptr(src), size) bulkBarrierPreWrite(uintptr(dst), uintptr(src), size)
} }
memmove(dst, src, size) memmove(dst, src, size)
...@@ -264,7 +264,7 @@ func typedslicecopy(typ *_type, dst, src slice) int { ...@@ -264,7 +264,7 @@ func typedslicecopy(typ *_type, dst, src slice) int {
return n return n
} }
// Note: No point in checking typ.kind&kindNoPointers here: // Note: No point in checking typ.ptrdata here:
// compiler only emits calls to typedslicecopy for types with pointers, // compiler only emits calls to typedslicecopy for types with pointers,
// and growslice and reflect_typedslicecopy check for pointers // and growslice and reflect_typedslicecopy check for pointers
// before calling typedslicecopy. // before calling typedslicecopy.
...@@ -280,7 +280,7 @@ func typedslicecopy(typ *_type, dst, src slice) int { ...@@ -280,7 +280,7 @@ func typedslicecopy(typ *_type, dst, src slice) int {
//go:linkname reflect_typedslicecopy reflect.typedslicecopy //go:linkname reflect_typedslicecopy reflect.typedslicecopy
func reflect_typedslicecopy(elemType *_type, dst, src slice) int { func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
if elemType.kind&kindNoPointers != 0 { if elemType.ptrdata == 0 {
n := dst.len n := dst.len
if n > src.len { if n > src.len {
n = src.len n = src.len
...@@ -317,7 +317,7 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int { ...@@ -317,7 +317,7 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
// //
//go:nosplit //go:nosplit
func typedmemclr(typ *_type, ptr unsafe.Pointer) { func typedmemclr(typ *_type, ptr unsafe.Pointer) {
if typ.kind&kindNoPointers == 0 { if typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(ptr), 0, typ.size) bulkBarrierPreWrite(uintptr(ptr), 0, typ.size)
} }
memclrNoHeapPointers(ptr, typ.size) memclrNoHeapPointers(ptr, typ.size)
...@@ -330,7 +330,7 @@ func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) { ...@@ -330,7 +330,7 @@ func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
//go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial //go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial
func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) { func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) {
if typ.kind&kindNoPointers == 0 { if typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(ptr), 0, size) bulkBarrierPreWrite(uintptr(ptr), 0, size)
} }
memclrNoHeapPointers(ptr, size) memclrNoHeapPointers(ptr, size)
...@@ -338,7 +338,7 @@ func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintpt ...@@ -338,7 +338,7 @@ func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintpt
// memclrHasPointers clears n bytes of typed memory starting at ptr. // memclrHasPointers clears n bytes of typed memory starting at ptr.
// The caller must ensure that the type of the object at ptr has // The caller must ensure that the type of the object at ptr has
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr // pointers, usually by checking typ.ptrdata. However, ptr
// does not have to point to the start of the allocation. // does not have to point to the start of the allocation.
// //
//go:nosplit //go:nosplit
......
...@@ -581,7 +581,7 @@ func (h heapBits) setCheckmarked(size uintptr) { ...@@ -581,7 +581,7 @@ func (h heapBits) setCheckmarked(size uintptr) {
// The pointer bitmap is not maintained for allocations containing // The pointer bitmap is not maintained for allocations containing
// no pointers at all; any caller of bulkBarrierPreWrite must first // no pointers at all; any caller of bulkBarrierPreWrite must first
// make sure the underlying allocation contains pointers, usually // make sure the underlying allocation contains pointers, usually
// by checking typ.kind&kindNoPointers. // by checking typ.ptrdata.
// //
// Callers must perform cgo checks if writeBarrier.cgo. // Callers must perform cgo checks if writeBarrier.cgo.
// //
......
...@@ -356,7 +356,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) { ...@@ -356,7 +356,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
if uintptr(e.data) != base { if uintptr(e.data) != base {
// As an implementation detail we allow to set finalizers for an inner byte // As an implementation detail we allow to set finalizers for an inner byte
// of an object if it could come from tiny alloc (see mallocgc for details). // of an object if it could come from tiny alloc (see mallocgc for details).
if ot.elem == nil || ot.elem.kind&kindNoPointers == 0 || ot.elem.size >= maxTinySize { if ot.elem == nil || ot.elem.ptrdata != 0 || ot.elem.size >= maxTinySize {
throw("runtime.SetFinalizer: pointer not at beginning of allocated block") throw("runtime.SetFinalizer: pointer not at beginning of allocated block")
} }
} }
......
...@@ -171,7 +171,7 @@ func growslice(et *_type, old slice, cap int) slice { ...@@ -171,7 +171,7 @@ func growslice(et *_type, old slice, cap int) slice {
} }
var p unsafe.Pointer var p unsafe.Pointer
if et.kind&kindNoPointers != 0 { if et.ptrdata == 0 {
p = mallocgc(capmem, nil, false) p = mallocgc(capmem, nil, false)
// 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.
......
...@@ -34,7 +34,6 @@ const ( ...@@ -34,7 +34,6 @@ const (
kindDirectIface = 1 << 5 kindDirectIface = 1 << 5
kindGCProg = 1 << 6 kindGCProg = 1 << 6
kindNoPointers = 1 << 7
kindMask = (1 << 5) - 1 kindMask = (1 << 5) - 1
) )
......
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