Commit 1354b32c authored by Rick Hudson's avatar Rick Hudson

[dev.garbage] runtime: add gc work buffer tryGet and put fast paths

The complexity of the GC work buffers put and tryGet
prevented them from being inlined. This CL simplifies
the fast path thus enabling inlining. If the fast
path does not succeed the previous put and tryGet
functions are called.

Change-Id: I6da6495d0dadf42bd0377c110b502274cc01acf5
Reviewed-on: https://go-review.googlesource.com/20704Reviewed-by: default avatarAustin Clements <austin@google.com>
parent f8d0d4fd
...@@ -831,7 +831,10 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { ...@@ -831,7 +831,10 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
if blocking { if blocking {
b = gcw.get() b = gcw.get()
} else { } else {
b = gcw.tryGet() b = gcw.tryGetFast()
if b == 0 {
b = gcw.tryGet()
}
} }
if b == 0 { if b == 0 {
// work barrier reached or tryGet failed. // work barrier reached or tryGet failed.
...@@ -894,7 +897,11 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { ...@@ -894,7 +897,11 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 {
// PREFETCH(wbuf->obj[wbuf.nobj - 3]; // PREFETCH(wbuf->obj[wbuf.nobj - 3];
// } // }
// //
b := gcw.tryGet() b := gcw.tryGetFast()
if b == 0 {
b = gcw.tryGet()
}
if b == 0 { if b == 0 {
break break
} }
...@@ -1087,8 +1094,9 @@ func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork ...@@ -1087,8 +1094,9 @@ func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork
// Previously we put the obj in an 8 element buffer that is drained at a rate // Previously we put the obj in an 8 element buffer that is drained at a rate
// to give the PREFETCH time to do its work. // to give the PREFETCH time to do its work.
// Use of PREFETCHNTA might be more appropriate than PREFETCH // Use of PREFETCHNTA might be more appropriate than PREFETCH
if !gcw.putFast(obj) {
gcw.put(obj) gcw.put(obj)
}
} }
// gcDumpObject dumps the contents of obj for debugging and marks the // gcDumpObject dumps the contents of obj for debugging and marks the
......
...@@ -116,6 +116,22 @@ func (w *gcWork) put(obj uintptr) { ...@@ -116,6 +116,22 @@ func (w *gcWork) put(obj uintptr) {
wbuf.nobj++ wbuf.nobj++
} }
// putFast does a put and returns true if it can be done quickly
// otherwise it returns false and the caller needs to call put.
//go:nowritebarrier
func (w *gcWork) putFast(obj uintptr) bool {
wbuf := w.wbuf1.ptr()
if wbuf == nil {
return false
} else if wbuf.nobj == len(wbuf.obj) {
return false
}
wbuf.obj[wbuf.nobj] = obj
wbuf.nobj++
return true
}
// tryGet dequeues a pointer for the garbage collector to trace. // tryGet dequeues a pointer for the garbage collector to trace.
// //
// If there are no pointers remaining in this gcWork or in the global // If there are no pointers remaining in this gcWork or in the global
...@@ -147,6 +163,23 @@ func (w *gcWork) tryGet() uintptr { ...@@ -147,6 +163,23 @@ func (w *gcWork) tryGet() uintptr {
return wbuf.obj[wbuf.nobj] return wbuf.obj[wbuf.nobj]
} }
// tryGetFast dequeues a pointer for the garbage collector to trace
// if one is readily available. Otherwise it returns 0 and
// the caller is expected to call tryGet().
//go:nowritebarrier
func (w *gcWork) tryGetFast() uintptr {
wbuf := w.wbuf1.ptr()
if wbuf == nil {
return 0
}
if wbuf.nobj == 0 {
return 0
}
wbuf.nobj--
return wbuf.obj[wbuf.nobj]
}
// get dequeues a pointer for the garbage collector to trace, blocking // get dequeues a pointer for the garbage collector to trace, blocking
// if necessary to ensure all pointers from all queues and caches have // if necessary to ensure all pointers from all queues and caches have
// been retrieved. get returns 0 if there are no pointers remaining. // been retrieved. get returns 0 if there are no pointers remaining.
......
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