]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/5g, cmd/6g, cmd/8g: preserve wide values in large functions
authorRuss Cox <rsc@golang.org>
Wed, 16 Apr 2014 17:59:42 +0000 (13:59 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 16 Apr 2014 17:59:42 +0000 (13:59 -0400)
In large functions with many variables, the register optimizer
may give up and choose not to track certain variables at all.
In this case, the "nextinnode" information linking together
all the words from a given variable will be incomplete, and
the result may be that only some of a multiword value is
preserved across a call. That confuses the garbage collector,
so don't do that. Instead, mark those variables as having
their address taken, so that they will be preserved at all
calls. It's overkill, but correct.

Tested by hand using the 6g -S output to see that it does fix
the buggy generated code leading to the issue 7726 failure.

There is no automated test because I managed to break the
compiler while writing a test (see issue 7727). I will check
in a test along with the fix to issue 7727.

Fixes #7726.

LGTM=khr
R=khr, bradfitz, dave
CC=golang-codereviews
https://golang.org/cl/85200043

src/cmd/5g/reg.c
src/cmd/6g/reg.c
src/cmd/8g/reg.c

index 47c2bedd7b1715dde98ba0494addc4f64a8be2e8..8350e4c50cb90d915bd5ce3e8935681a3fe59754 100644 (file)
@@ -801,6 +801,16 @@ mkvar(Reg *r, Adr *a)
        if(nvar >= NVAR) {
                if(debug['w'] > 1 && node)
                        fatal("variable not optimized: %D", a);
+               
+               // If we're not tracking a word in a variable, mark the rest as
+               // having its address taken, so that we keep the whole thing
+               // live at all calls. otherwise we might optimize away part of
+               // a variable but not all of it.
+               for(i=0; i<nvar; i++) {
+                       v = var+i;
+                       if(v->node == node)
+                               v->addr = 1;
+               }
                goto none;
        }
 
index 3e5b1c586514335780d027df171a091a3c4e3c21..0c72d6c95cdf4eaa228345ad9b4d8f0e1d123871 100644 (file)
@@ -659,6 +659,16 @@ mkvar(Reg *r, Adr *a)
        if(nvar >= NVAR) {
                if(debug['w'] > 1 && node != N)
                        fatal("variable not optimized: %#N", node);
+               
+               // If we're not tracking a word in a variable, mark the rest as
+               // having its address taken, so that we keep the whole thing
+               // live at all calls. otherwise we might optimize away part of
+               // a variable but not all of it.
+               for(i=0; i<nvar; i++) {
+                       v = var+i;
+                       if(v->node == node)
+                               v->addr = 1;
+               }
                goto none;
        }
 
index e8e712495c0c2cc09601e17c33a36a3f59bdeb27..1e8a31dd62ea4b4c991c0a5aeaad052512219f0e 100644 (file)
@@ -625,6 +625,16 @@ mkvar(Reg *r, Adr *a)
        if(nvar >= NVAR) {
                if(debug['w'] > 1 && node != N)
                        fatal("variable not optimized: %D", a);
+               
+               // If we're not tracking a word in a variable, mark the rest as
+               // having its address taken, so that we keep the whole thing
+               // live at all calls. otherwise we might optimize away part of
+               // a variable but not all of it.
+               for(i=0; i<nvar; i++) {
+                       v = var+i;
+                       if(v->node == node)
+                               v->addr = 1;
+               }
                goto none;
        }