aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/runtime.def2
-rw-r--r--gcc/go/gofrontend/wb.cc6
-rw-r--r--libgo/go/runtime/mgc_gccgo.go12
-rw-r--r--libgo/go/runtime/proc.go35
5 files changed, 31 insertions, 26 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 9a789b9..67ed658 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-82d7205ba9e5c1fe38fd24f89a45caf2e974975b
+218c9159635e06e39ae43d0efe1ac1e694fead2e
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 1486cd8..ed759e8 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -302,7 +302,7 @@ DEF_GO_RUNTIME(IFACEEFACEEQ, "runtime.ifaceefaceeq", P2(IFACE, EFACE),
// Set *dst = src where dst is a pointer to a pointer and src is a pointer.
-DEF_GO_RUNTIME(WRITEBARRIERPTR, "runtime.writebarrierptr",
+DEF_GO_RUNTIME(GCWRITEBARRIER, "runtime.gcWriteBarrier",
P2(POINTER, POINTER), R0())
// Set *dst = *src for an arbitrary type.
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc
index 4944b68..4f84d99 100644
--- a/gcc/go/gofrontend/wb.cc
+++ b/gcc/go/gofrontend/wb.cc
@@ -380,7 +380,7 @@ Gogo::propagate_writebarrierrec()
// This is compatible with the definition in the runtime package.
//
// For types that are pointer shared (pointers, maps, chans, funcs),
-// we replaced the call to typedmemmove with writebarrierptr(&A, B).
+// we replaced the call to typedmemmove with gcWriteBarrier(&A, B).
// As far as the GC is concerned, all pointers are the same, so it
// doesn't need the type descriptor.
//
@@ -391,7 +391,7 @@ Gogo::propagate_writebarrierrec()
// runtime package, so we could optimize by only testing it once
// between function calls.
//
-// A slice could be handled with a call to writebarrierptr plus two
+// A slice could be handled with a call to gcWriteBarrier plus two
// integer moves.
// Traverse the IR adding write barriers.
@@ -824,7 +824,7 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
case Type::TYPE_MAP:
case Type::TYPE_CHANNEL:
// These types are all represented by a single pointer.
- call = Runtime::make_call(Runtime::WRITEBARRIERPTR, loc, 2, lhs, rhs);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
break;
case Type::TYPE_STRING:
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()