mirror of
https://github.com/golang/go
synced 2024-11-19 16:44:43 -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:
parent
b78b54ff83
commit
164e1b8477
@ -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.
|
||||||
|
@ -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{
|
||||||
|
Loading…
Reference in New Issue
Block a user