]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
compiler, runtime: call gcWriteBarrier instead of writebarrierptr
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Sep 2018 22:25:58 +0000 (22:25 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Sep 2018 22:25:58 +0000 (22:25 +0000)
    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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@264295 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/runtime.def
gcc/go/gofrontend/wb.cc
libgo/go/runtime/mgc_gccgo.go
libgo/go/runtime/proc.go

index 9a789b970e054e3be3350e71f52330828fc03e1a..67ed6589ad14a859bb4ef0996aba9ec0090e2534 100644 (file)
@@ -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.
index 1486cd85f27f6dbdfa6f83cf6fc0646d6337debf..ed759e80780ddbfe0733e859762b06b8ccee629a 100644 (file)
@@ -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.
index 4944b68fccf7d741003d7be9dc02923bc455544a..4f84d9950f1a2808f45fcbe92141d546666437bd 100644 (file)
@@ -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:
index cf7780c37f4cfe47f3b25c93fd06df12fa0bf9e1..b396d35146cb77c609fdfb2d7b1bc9158f0f3e96 100644 (file)
@@ -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
index 12d7071c3c0fe8901b89bedac7e8c290fcfe63fc..4fc45dd4f64c59d31ac3c7765260832c79cdbf08 100644 (file)
@@ -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()