aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRick Hudson <rlh@golang.org>2016-03-14 12:17:48 -0400
committerRick Hudson <rlh@golang.org>2016-04-27 21:55:02 +0000
commit1354b32cd70f2702381764fd595dd2faa996840c (patch)
tree0d7037b41cc57a1003277c8cf55d527adab58b7d /src
parentf8d0d4fd59b6cb6f875eac7753f036b10a28f995 (diff)
downloadgo-1354b32cd70f2702381764fd595dd2faa996840c.tar.xz
[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/20704 Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/mgcmark.go16
-rw-r--r--src/runtime/mgcwork.go33
2 files changed, 45 insertions, 4 deletions
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index 47456857e9..d05ad6549f 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -831,7 +831,10 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
if blocking {
b = gcw.get()
} else {
- b = gcw.tryGet()
+ b = gcw.tryGetFast()
+ if b == 0 {
+ b = gcw.tryGet()
+ }
}
if b == 0 {
// work barrier reached or tryGet failed.
@@ -894,7 +897,11 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 {
// PREFETCH(wbuf->obj[wbuf.nobj - 3];
// }
//
- b := gcw.tryGet()
+ b := gcw.tryGetFast()
+ if b == 0 {
+ b = gcw.tryGet()
+ }
+
if b == 0 {
break
}
@@ -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
// to give the PREFETCH time to do its work.
// Use of PREFETCHNTA might be more appropriate than PREFETCH
-
- gcw.put(obj)
+ if !gcw.putFast(obj) {
+ gcw.put(obj)
+ }
}
// gcDumpObject dumps the contents of obj for debugging and marks the
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index 63a3ade3a6..d04840b686 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -116,6 +116,22 @@ func (w *gcWork) put(obj uintptr) {
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.
//
// If there are no pointers remaining in this gcWork or in the global
@@ -147,6 +163,23 @@ func (w *gcWork) tryGet() uintptr {
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
// if necessary to ensure all pointers from all queues and caches have
// been retrieved. get returns 0 if there are no pointers remaining.