mirror of https://github.com/golang/go.git
runtime: remove wbufptr
Since workbuf is now marked go:notinheap, the write barrier-preventing wrapper type wbufptr is no longer necessary. Remove it. Change-Id: I3e5b5803a1547d65de1c1a9c22458a38e08549b7 Reviewed-on: https://go-review.googlesource.com/35971 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
8eb14e9de5
commit
98da2d1f91
|
|
@ -25,21 +25,6 @@ const (
|
||||||
// grey objects, thus blackening them, and then scans them,
|
// grey objects, thus blackening them, and then scans them,
|
||||||
// potentially producing new pointers to grey objects.
|
// potentially producing new pointers to grey objects.
|
||||||
|
|
||||||
// A wbufptr holds a workbuf*, but protects it from write barriers.
|
|
||||||
// workbufs never live on the heap, so write barriers are unnecessary.
|
|
||||||
// Write barriers on workbuf pointers may also be dangerous in the GC.
|
|
||||||
//
|
|
||||||
// TODO: Since workbuf is now go:notinheap, this isn't necessary.
|
|
||||||
type wbufptr uintptr
|
|
||||||
|
|
||||||
func wbufptrOf(w *workbuf) wbufptr {
|
|
||||||
return wbufptr(unsafe.Pointer(w))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wp wbufptr) ptr() *workbuf {
|
|
||||||
return (*workbuf)(unsafe.Pointer(wp))
|
|
||||||
}
|
|
||||||
|
|
||||||
// A gcWork provides the interface to produce and consume work for the
|
// A gcWork provides the interface to produce and consume work for the
|
||||||
// garbage collector.
|
// garbage collector.
|
||||||
//
|
//
|
||||||
|
|
@ -75,7 +60,7 @@ type gcWork struct {
|
||||||
// next.
|
// next.
|
||||||
//
|
//
|
||||||
// Invariant: Both wbuf1 and wbuf2 are nil or neither are.
|
// Invariant: Both wbuf1 and wbuf2 are nil or neither are.
|
||||||
wbuf1, wbuf2 wbufptr
|
wbuf1, wbuf2 *workbuf
|
||||||
|
|
||||||
// Bytes marked (blackened) on this gcWork. This is aggregated
|
// Bytes marked (blackened) on this gcWork. This is aggregated
|
||||||
// into work.bytesMarked by dispose.
|
// into work.bytesMarked by dispose.
|
||||||
|
|
@ -87,12 +72,12 @@ type gcWork struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *gcWork) init() {
|
func (w *gcWork) init() {
|
||||||
w.wbuf1 = wbufptrOf(getempty())
|
w.wbuf1 = getempty()
|
||||||
wbuf2 := trygetfull()
|
wbuf2 := trygetfull()
|
||||||
if wbuf2 == nil {
|
if wbuf2 == nil {
|
||||||
wbuf2 = getempty()
|
wbuf2 = getempty()
|
||||||
}
|
}
|
||||||
w.wbuf2 = wbufptrOf(wbuf2)
|
w.wbuf2 = wbuf2
|
||||||
}
|
}
|
||||||
|
|
||||||
// put enqueues a pointer for the garbage collector to trace.
|
// put enqueues a pointer for the garbage collector to trace.
|
||||||
|
|
@ -100,18 +85,18 @@ func (w *gcWork) init() {
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) put(obj uintptr) {
|
func (w *gcWork) put(obj uintptr) {
|
||||||
flushed := false
|
flushed := false
|
||||||
wbuf := w.wbuf1.ptr()
|
wbuf := w.wbuf1
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
w.init()
|
w.init()
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
// wbuf is empty at this point.
|
// wbuf is empty at this point.
|
||||||
} else if wbuf.nobj == len(wbuf.obj) {
|
} else if wbuf.nobj == len(wbuf.obj) {
|
||||||
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
if wbuf.nobj == len(wbuf.obj) {
|
if wbuf.nobj == len(wbuf.obj) {
|
||||||
putfull(wbuf)
|
putfull(wbuf)
|
||||||
wbuf = getempty()
|
wbuf = getempty()
|
||||||
w.wbuf1 = wbufptrOf(wbuf)
|
w.wbuf1 = wbuf
|
||||||
flushed = true
|
flushed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +117,7 @@ func (w *gcWork) put(obj uintptr) {
|
||||||
// otherwise it returns false and the caller needs to call put.
|
// otherwise it returns false and the caller needs to call put.
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) putFast(obj uintptr) bool {
|
func (w *gcWork) putFast(obj uintptr) bool {
|
||||||
wbuf := w.wbuf1.ptr()
|
wbuf := w.wbuf1
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
return false
|
return false
|
||||||
} else if wbuf.nobj == len(wbuf.obj) {
|
} else if wbuf.nobj == len(wbuf.obj) {
|
||||||
|
|
@ -151,15 +136,15 @@ func (w *gcWork) putFast(obj uintptr) bool {
|
||||||
// other gcWork instances or other caches.
|
// other gcWork instances or other caches.
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) tryGet() uintptr {
|
func (w *gcWork) tryGet() uintptr {
|
||||||
wbuf := w.wbuf1.ptr()
|
wbuf := w.wbuf1
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
w.init()
|
w.init()
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
// wbuf is empty at this point.
|
// wbuf is empty at this point.
|
||||||
}
|
}
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
owbuf := wbuf
|
owbuf := wbuf
|
||||||
wbuf = trygetfull()
|
wbuf = trygetfull()
|
||||||
|
|
@ -167,7 +152,7 @@ func (w *gcWork) tryGet() uintptr {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
putempty(owbuf)
|
putempty(owbuf)
|
||||||
w.wbuf1 = wbufptrOf(wbuf)
|
w.wbuf1 = wbuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +165,7 @@ func (w *gcWork) tryGet() uintptr {
|
||||||
// the caller is expected to call tryGet().
|
// the caller is expected to call tryGet().
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) tryGetFast() uintptr {
|
func (w *gcWork) tryGetFast() uintptr {
|
||||||
wbuf := w.wbuf1.ptr()
|
wbuf := w.wbuf1
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -197,15 +182,15 @@ func (w *gcWork) tryGetFast() uintptr {
|
||||||
// been retrieved. get returns 0 if there are no pointers remaining.
|
// been retrieved. get returns 0 if there are no pointers remaining.
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) get() uintptr {
|
func (w *gcWork) get() uintptr {
|
||||||
wbuf := w.wbuf1.ptr()
|
wbuf := w.wbuf1
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
w.init()
|
w.init()
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
// wbuf is empty at this point.
|
// wbuf is empty at this point.
|
||||||
}
|
}
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
|
||||||
wbuf = w.wbuf1.ptr()
|
wbuf = w.wbuf1
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
owbuf := wbuf
|
owbuf := wbuf
|
||||||
wbuf = getfull()
|
wbuf = getfull()
|
||||||
|
|
@ -213,7 +198,7 @@ func (w *gcWork) get() uintptr {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
putempty(owbuf)
|
putempty(owbuf)
|
||||||
w.wbuf1 = wbufptrOf(wbuf)
|
w.wbuf1 = wbuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,21 +216,21 @@ func (w *gcWork) get() uintptr {
|
||||||
//
|
//
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) dispose() {
|
func (w *gcWork) dispose() {
|
||||||
if wbuf := w.wbuf1.ptr(); wbuf != nil {
|
if wbuf := w.wbuf1; wbuf != nil {
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
putempty(wbuf)
|
putempty(wbuf)
|
||||||
} else {
|
} else {
|
||||||
putfull(wbuf)
|
putfull(wbuf)
|
||||||
}
|
}
|
||||||
w.wbuf1 = 0
|
w.wbuf1 = nil
|
||||||
|
|
||||||
wbuf = w.wbuf2.ptr()
|
wbuf = w.wbuf2
|
||||||
if wbuf.nobj == 0 {
|
if wbuf.nobj == 0 {
|
||||||
putempty(wbuf)
|
putempty(wbuf)
|
||||||
} else {
|
} else {
|
||||||
putfull(wbuf)
|
putfull(wbuf)
|
||||||
}
|
}
|
||||||
w.wbuf2 = 0
|
w.wbuf2 = nil
|
||||||
}
|
}
|
||||||
if w.bytesMarked != 0 {
|
if w.bytesMarked != 0 {
|
||||||
// dispose happens relatively infrequently. If this
|
// dispose happens relatively infrequently. If this
|
||||||
|
|
@ -265,14 +250,14 @@ func (w *gcWork) dispose() {
|
||||||
// global queue.
|
// global queue.
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) balance() {
|
func (w *gcWork) balance() {
|
||||||
if w.wbuf1 == 0 {
|
if w.wbuf1 == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if wbuf := w.wbuf2.ptr(); wbuf.nobj != 0 {
|
if wbuf := w.wbuf2; wbuf.nobj != 0 {
|
||||||
putfull(wbuf)
|
putfull(wbuf)
|
||||||
w.wbuf2 = wbufptrOf(getempty())
|
w.wbuf2 = getempty()
|
||||||
} else if wbuf := w.wbuf1.ptr(); wbuf.nobj > 4 {
|
} else if wbuf := w.wbuf1; wbuf.nobj > 4 {
|
||||||
w.wbuf1 = wbufptrOf(handoff(wbuf))
|
w.wbuf1 = handoff(wbuf)
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -285,7 +270,7 @@ func (w *gcWork) balance() {
|
||||||
// empty returns true if w has no mark work available.
|
// empty returns true if w has no mark work available.
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func (w *gcWork) empty() bool {
|
func (w *gcWork) empty() bool {
|
||||||
return w.wbuf1 == 0 || (w.wbuf1.ptr().nobj == 0 && w.wbuf2.ptr().nobj == 0)
|
return w.wbuf1 == nil || (w.wbuf1.nobj == 0 && w.wbuf2.nobj == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internally, the GC work pool is kept in arrays in work buffers.
|
// Internally, the GC work pool is kept in arrays in work buffers.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue