diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-09-13 22:25:58 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-09-13 22:25:58 +0000 |
commit | cec07c4759e8af44ca77a2beb9312e4e30d1cc7a (patch) | |
tree | 38fe52c7aeba372693d83041bf5037d8fbb2c311 /libgo | |
parent | 38fab7369d19fd545eb8510ec198e73949a2c75d (diff) | |
download | gcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.zip gcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.tar.gz gcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.tar.bz2 |
compiler, runtime: call gcWriteBarrier instead of writebarrierptr
In 1.11 writebarrierptr is going away, so change the compiler to call
gcWriteBarrier instead. We weren't using gcWriteBarrier before;
adjust the implementation to use the putFast method.
This revealed a problem in the kickoff function. When using cgo,
kickoff can be called on the g0 of an m allocated by newExtraM. In
that case the m will generally have a p, but systemstack may be called
by wbBufFlush as part of flushing the write barrier buffer. At that
point the buffer is full, so we can not do a write barrier. So adjust
the existing code in kickoff so that in the case where we are g0,
don't do any write barrier at all.
Reviewed-on: https://go-review.googlesource.com/131395
From-SVN: r264295
Diffstat (limited to 'libgo')
-rw-r--r-- | libgo/go/runtime/mgc_gccgo.go | 12 | ||||
-rw-r--r-- | libgo/go/runtime/proc.go | 35 |
2 files changed, 26 insertions, 21 deletions
diff --git a/libgo/go/runtime/mgc_gccgo.go b/libgo/go/runtime/mgc_gccgo.go index cf7780c..b396d35 100644 --- a/libgo/go/runtime/mgc_gccgo.go +++ b/libgo/go/runtime/mgc_gccgo.go @@ -11,6 +11,11 @@ import ( "unsafe" ) +// For gccgo, use go:linkname to rename compiler-called functions to +// themselves, so that the compiler will export them. +// +//go:linkname gcWriteBarrier runtime.gcWriteBarrier + // gcRoot is a single GC root: a variable plus a ptrmask. //go:notinheap type gcRoot struct { @@ -188,12 +193,7 @@ func checkPreempt() { //go:nowritebarrier func gcWriteBarrier(dst *uintptr, src uintptr) { buf := &getg().m.p.ptr().wbBuf - next := buf.next - np := next + 2*sys.PtrSize - buf.next = np - *(*uintptr)(unsafe.Pointer(next)) = src - *(*uintptr)(unsafe.Pointer(next + sys.PtrSize)) = *dst - if np >= buf.end { + if !buf.putFast(src, *dst) { wbBufFlush(dst, src) } *dst = src diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 12d7071..4fc45dd 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -1146,24 +1146,29 @@ func kickoff() { fv := gp.entry param := gp.param - gp.entry = nil // When running on the g0 stack we can wind up here without a p, - // for example from mcall(exitsyscall0) in exitsyscall. - // Setting gp.param = nil will call a write barrier, and if - // there is no p that write barrier will crash. When called from - // mcall the gp.param value will be a *g, which we don't need to - // shade since we know it will be kept alive elsewhere. In that - // case clear the field using uintptr so that the write barrier - // does nothing. - if gp.m.p == 0 { - if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) { - *(*uintptr)(unsafe.Pointer(&gp.param)) = 0 - } else { - throw("no p in kickoff") - } + // for example from mcall(exitsyscall0) in exitsyscall, in + // which case we can not run a write barrier. + // It is also possible for us to get here from the systemstack + // call in wbBufFlush, at which point the write barrier buffer + // is full and we can not run a write barrier. + // Setting gp.entry = nil or gp.param = nil will try to run a + // write barrier, so if we are on the g0 stack due to mcall + // (systemstack calls mcall) then clear the field using uintptr. + // This is OK when gp.param is gp.m.curg, as curg will be kept + // alive elsewhere, and gp.entry always points into g, or + // to a statically allocated value, or (in the case of mcall) + // to the stack. + if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) { + *(*uintptr)(unsafe.Pointer(&gp.entry)) = 0 + *(*uintptr)(unsafe.Pointer(&gp.param)) = 0 + } else if gp.m.p == 0 { + throw("no p in kickoff") + } else { + gp.entry = nil + gp.param = nil } - gp.param = nil fv(param) goexit1() |