From: Russ Cox Date: Mon, 18 May 2015 20:54:59 +0000 (-0400) Subject: cmd/internal/gc: add missing write barrier in append(x, BigStructWithPointers) X-Git-Tag: go1.5beta1~532 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=366ba526e88f5b523298d3ad5014e04a495add82;p=gostls13.git cmd/internal/gc: add missing write barrier in append(x, BigStructWithPointers) Fixes #10897. Change-Id: I5c2d1f9d26333e2b2a0613ebf496daa465e07c24 Reviewed-on: https://go-review.googlesource.com/10221 Reviewed-by: Austin Clements --- diff --git a/src/cmd/internal/gc/cgen.go b/src/cmd/internal/gc/cgen.go index bb022b8351..002439ce36 100644 --- a/src/cmd/internal/gc/cgen.go +++ b/src/cmd/internal/gc/cgen.go @@ -2156,14 +2156,27 @@ func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) { } } -/* - * n is on stack, either local variable - * or return value from function call. - * return n's offset from SP. - */ +// stkof returns n's offset from SP if n is on the stack +// (either a local variable or the return value from a function call +// or the arguments to a function call). +// If n is not on the stack, stkof returns -1000. +// If n is on the stack but in an unknown location +// (due to array index arithmetic), stkof returns +1000. +// +// NOTE(rsc): It is possible that the ODOT and OINDEX cases +// are not relevant here, since it shouldn't be possible for them +// to be involved in an overlapping copy. Only function results +// from one call and the arguments to the next can overlap in +// any non-trivial way. If they can be dropped, then this function +// becomes much simpler and also more trustworthy. +// The fact that it works at all today is probably due to the fact +// that ODOT and OINDEX are irrelevant. func stkof(n *Node) int64 { switch n.Op { case OINDREG: + if n.Reg != int16(Thearch.REGSP) { + return -1000 // not on stack + } return n.Xoffset case ODOT: @@ -2172,7 +2185,7 @@ func stkof(n *Node) int64 { break } off := stkof(n.Left) - if off == -1000 || off == 1000 { + if off == -1000 || off == +1000 { return off } return off + n.Xoffset @@ -2183,13 +2196,13 @@ func stkof(n *Node) int64 { break } off := stkof(n.Left) - if off == -1000 || off == 1000 { + if off == -1000 || off == +1000 { return off } if Isconst(n.Right, CTINT) { return off + t.Type.Width*Mpgetfix(n.Right.Val.U.(*Mpint)) } - return 1000 + return +1000 // on stack but not sure exactly where case OCALLMETH, OCALLINTER, OCALLFUNC: t := n.Left.Type @@ -2210,7 +2223,7 @@ func stkof(n *Node) int64 { // botch - probably failing to recognize address // arithmetic on the above. eg INDEX and DOT - return -1000 + return -1000 // not on stack } /* diff --git a/test/writebarrier.go b/test/writebarrier.go index b24af9a14d..9b741a60df 100644 --- a/test/writebarrier.go +++ b/test/writebarrier.go @@ -128,3 +128,19 @@ func f13(x []int, y *[]int) { func f14(y *[]int) { *y = append(*y, 1) // ERROR "write barrier" } + +type T1 struct { + X *int +} + +func f15(x []T1, y T1) []T1 { + return append(x, y) // ERROR "write barrier" +} + +type T8 struct { + X [8]*int +} + +func f16(x []T8, y T8) []T8 { + return append(x, y) // ERROR "write barrier" +}