Commit ff6d0a4d authored by Russ Cox's avatar Russ Cox

cmd/gc, runtime: fix race, nacl for writebarrier changes

The racewalk code was not updated for the new write barriers.
Make it more future-proof.

The new write barrier code assumed that +1 pointer would
be aligned properly for any type that might follow, but that's
not true on 32-bit systems where some types are 64-bit aligned.
The only system like that today is nacl/amd64p32.
Insert a dummy pointer so that the ambiguously typed
value is at +2 pointers, which is always max-aligned.

LGTM=r
R=r
CC=golang-codereviews, iant, khr
https://golang.org/cl/158890046
parent ae250ab2
...@@ -87,9 +87,9 @@ char *runtimeimport = ...@@ -87,9 +87,9 @@ char *runtimeimport =
"func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n"
"func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n"
"func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n"
"func @\"\".writebarrierfat2 (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierfat2 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
"func @\"\".writebarrierfat3 (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierfat3 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
"func @\"\".writebarrierfat4 (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierfat4 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
"func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n" "func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n"
"func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n" "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n" "func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
......
...@@ -210,12 +210,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) ...@@ -210,12 +210,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OCALLFUNC: case OCALLFUNC:
// Instrument dst argument of runtime.writebarrier* calls // Instrument dst argument of runtime.writebarrier* calls
// as we do not instrument runtime code. // as we do not instrument runtime code.
if(n->left->sym != S && n->left->sym->pkg == runtimepkg && if(n->left->sym != S && n->left->sym->pkg == runtimepkg && strncmp(n->left->sym->name, "writebarrier", 12) == 0) {
(strcmp(n->left->sym->name, "writebarrierptr") == 0 ||
strcmp(n->left->sym->name, "writebarrierstring") == 0 ||
strcmp(n->left->sym->name, "writebarrierslice") == 0 ||
strcmp(n->left->sym->name, "writebarrieriface") == 0 ||
strcmp(n->left->sym->name, "writebarrierfat") == 0)) {
// Find the dst argument. // Find the dst argument.
// The list can be reordered, so it's not necessary just the first or the second element. // The list can be reordered, so it's not necessary just the first or the second element.
for(l = n->list; l; l = l->next) { for(l = n->list; l; l = l->next) {
......
...@@ -112,9 +112,13 @@ func writebarrierptr(dst *any, src any) ...@@ -112,9 +112,13 @@ func writebarrierptr(dst *any, src any)
func writebarrierstring(dst *any, src any) func writebarrierstring(dst *any, src any)
func writebarrierslice(dst *any, src any) func writebarrierslice(dst *any, src any)
func writebarrieriface(dst *any, src any) func writebarrieriface(dst *any, src any)
func writebarrierfat2(dst *any, src any)
func writebarrierfat3(dst *any, src any) // The unused *byte argument makes sure that src is 2-pointer-aligned,
func writebarrierfat4(dst *any, src any) // which is the maximum alignment on NaCl amd64p32
// (and possibly on 32-bit systems if we start 64-bit aligning uint64s).
func writebarrierfat2(dst *any, _ *byte, src any)
func writebarrierfat3(dst *any, _ *byte, src any)
func writebarrierfat4(dst *any, _ *byte, src any)
func writebarrierfat(typ *byte, dst *any, src *any) func writebarrierfat(typ *byte, dst *any, src *any)
func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
......
...@@ -2060,13 +2060,13 @@ applywritebarrier(Node *n, NodeList **init) ...@@ -2060,13 +2060,13 @@ applywritebarrier(Node *n, NodeList **init)
l, n->right); l, n->right);
} else if(t->width == 2*widthptr) { } else if(t->width == 2*widthptr) {
n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init, n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init,
l, n->right); l, nodnil(), n->right);
} else if(t->width == 3*widthptr) { } else if(t->width == 3*widthptr) {
n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init, n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init,
l, n->right); l, nodnil(), n->right);
} else if(t->width == 4*widthptr) { } else if(t->width == 4*widthptr) {
n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init, n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init,
l, n->right); l, nodnil(), n->right);
} else { } else {
r = n->right; r = n->right;
while(r->op == OCONVNOP) while(r->op == OCONVNOP)
......
...@@ -110,20 +110,20 @@ func writebarrieriface(dst *[2]uintptr, src [2]uintptr) { ...@@ -110,20 +110,20 @@ func writebarrieriface(dst *[2]uintptr, src [2]uintptr) {
} }
//go:nosplit //go:nosplit
func writebarrierfat2(dst *[2]uintptr, src [2]uintptr) { func writebarrierfat2(dst *[2]uintptr, _ *byte, src [2]uintptr) {
dst[0] = src[0] dst[0] = src[0]
dst[1] = src[1] dst[1] = src[1]
} }
//go:nosplit //go:nosplit
func writebarrierfat3(dst *[3]uintptr, src [3]uintptr) { func writebarrierfat3(dst *[3]uintptr, _ *byte, src [3]uintptr) {
dst[0] = src[0] dst[0] = src[0]
dst[1] = src[1] dst[1] = src[1]
dst[2] = src[2] dst[2] = src[2]
} }
//go:nosplit //go:nosplit
func writebarrierfat4(dst *[4]uintptr, src [4]uintptr) { func writebarrierfat4(dst *[4]uintptr, _ *byte, src [4]uintptr) {
dst[0] = src[0] dst[0] = src[0]
dst[1] = src[1] dst[1] = src[1]
dst[2] = src[2] dst[2] = src[2]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment