1
0
mirror of https://github.com/golang/go synced 2024-11-19 14:14:40 -07:00

runtime: eliminate remaining recordspan write barriers

recordspan has two remaining write barriers from writing to the
pointer to the backing store of h.allspans. However, h.allspans is
always backed by off-heap memory, so let the compiler know this.
Unfortunately, this isn't quite as clean as most go:notinheap uses
because we can't directly name the backing store of a slice, but we
can get it done with some judicious casting.

For #22460.

Change-Id: I296f92fa41cf2cb6ae572b35749af23967533877
Reviewed-on: https://go-review.googlesource.com/73414
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2017-10-25 13:46:54 -04:00
parent b78b54ff83
commit 164e1b8477
2 changed files with 21 additions and 2 deletions

View File

@ -319,6 +319,17 @@ func (s *mspan) layout() (size, n, total uintptr) {
return return
} }
// recordspan adds a newly allocated span to h.allspans.
//
// This only happens the first time a span is allocated from
// mheap.spanalloc (it is not called when a span is reused).
//
// Write barriers are disallowed here because it can be called from
// gcWork when allocating new workbufs. However, because it's an
// indirect call from the fixalloc initializer, the compiler can't see
// this.
//
//go:nowritebarrierrec
func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { func recordspan(vh unsafe.Pointer, p unsafe.Pointer) {
h := (*mheap)(vh) h := (*mheap)(vh)
s := (*mspan)(p) s := (*mspan)(p)
@ -339,12 +350,13 @@ func recordspan(vh unsafe.Pointer, p unsafe.Pointer) {
copy(new, h.allspans) copy(new, h.allspans)
} }
oldAllspans := h.allspans oldAllspans := h.allspans
h.allspans = new *(*notInHeapSlice)(unsafe.Pointer(&h.allspans)) = *(*notInHeapSlice)(unsafe.Pointer(&new))
if len(oldAllspans) != 0 { if len(oldAllspans) != 0 {
sysFree(unsafe.Pointer(&oldAllspans[0]), uintptr(cap(oldAllspans))*unsafe.Sizeof(oldAllspans[0]), &memstats.other_sys) sysFree(unsafe.Pointer(&oldAllspans[0]), uintptr(cap(oldAllspans))*unsafe.Sizeof(oldAllspans[0]), &memstats.other_sys)
} }
} }
h.allspans = append(h.allspans, s) h.allspans = h.allspans[:len(h.allspans)+1]
h.allspans[len(h.allspans)-1] = s
} }
// A spanClass represents the size class and noscan-ness of a span. // A spanClass represents the size class and noscan-ness of a span.

View File

@ -14,6 +14,13 @@ type slice struct {
cap int cap int
} }
// An notInHeapSlice is a slice backed by go:notinheap memory.
type notInHeapSlice struct {
array *notInHeap
len int
cap int
}
// maxElems is a lookup table containing the maximum capacity for a slice. // maxElems is a lookup table containing the maximum capacity for a slice.
// The index is the size of the slice element. // The index is the size of the slice element.
var maxElems = [...]uintptr{ var maxElems = [...]uintptr{