Commit 557a61d2 authored by Russ Cox's avatar Russ Cox

cmd/gc: add //go:nowritebarrier to diagnose unintended write barriers

//go:nowritebarrier can only be used in package runtime.
It does not disable write barriers; it is an assertion, checked
by the compiler, that the following function needs no write
barriers.

Change-Id: Id7978b779b66dc1feea39ee6bda9fd4d80280b7c
Reviewed-on: https://go-review.googlesource.com/1224Reviewed-by: default avatarRick Hudson <rlh@golang.org>
parent 2fa657c5
......@@ -271,6 +271,7 @@ struct Node
uchar noescape; // func arguments do not escape
uchar nosplit; // func should not execute on separate stack
uchar builtin; // built-in name, like len or close
uchar nowritebarrier; // emit compiler error instead of write barrier
uchar walkdef;
uchar typecheck;
uchar local;
......@@ -987,6 +988,7 @@ EXTERN int flag_race;
EXTERN int flag_largemodel;
EXTERN int noescape;
EXTERN int nosplit;
EXTERN int nowritebarrier;
EXTERN int debuglive;
EXTERN Link* ctxt;
......
......@@ -1319,6 +1319,7 @@ xfndcl:
$$->endlineno = lineno;
$$->noescape = noescape;
$$->nosplit = nosplit;
$$->nowritebarrier = nowritebarrier;
funcbody($$);
}
......@@ -1502,6 +1503,7 @@ xdcl_list:
nointerface = 0;
noescape = 0;
nosplit = 0;
nowritebarrier = 0;
}
vardcl_list:
......
......@@ -1655,6 +1655,12 @@ go:
nosplit = 1;
goto out;
}
if(strcmp(lexbuf, "go:nowritebarrier") == 0) {
if(!compiling_runtime)
yyerror("//go:nowritebarrier only allowed in runtime");
nowritebarrier = 1;
goto out;
}
out:
return c;
......
......@@ -2010,6 +2010,8 @@ applywritebarrier(Node *n, NodeList **init)
char name[32];
if(n->left && n->right && needwritebarrier(n->left, n->right)) {
if(curfn && curfn->nowritebarrier)
yyerror("write barrier prohibited");
t = n->left->type;
l = nod(OADDR, n->left, N);
l->etype = 1; // addr does not escape
......
This diff is collapsed.
This diff is collapsed.
......@@ -1577,6 +1577,7 @@ func goexit0(gp *g) {
}
//go:nosplit
//go:nowritebarrier
func save(pc, sp uintptr) {
_g_ := getg()
......@@ -1585,7 +1586,7 @@ func save(pc, sp uintptr) {
_g_.sched.lr = 0
_g_.sched.ret = 0
_g_.sched.ctxt = nil
// write as uintptr to avoid write barrier, which will smash _g_.sched.
// _g_.sched.g = _g_, but avoid write barrier, which smashes _g_.sched
*(*uintptr)(unsafe.Pointer(&_g_.sched.g)) = uintptr(unsafe.Pointer(_g_))
}
......
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