From 30ecb4cd05ac41805593c95bd7967b808e5f4ca5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 16 Sep 2013 20:26:10 -0400 Subject: [PATCH] build: disable precise collection of stack frames The code for call site-specific pointer bitmaps was not ready in time, but the zeroing required without it is too expensive to use by default. We will have to wait for precise collection of stack frames until Go 1.3. The precise collection can be re-enabled by GOEXPERIMENT=precisestack ./all.bash but that will not be the default for a Go 1.2 build. Fixes #6087. R=golang-dev, jeremyjackins, dan.kortschak, r CC=golang-dev https://golang.org/cl/13677045 --- src/cmd/dist/a.h | 1 + src/cmd/dist/build.c | 2 ++ src/cmd/dist/buildruntime.c | 35 ++++++++++++++++++++++++++++++++++- src/cmd/gc/go.h | 1 + src/cmd/gc/lex.c | 1 + src/cmd/gc/pgen.c | 20 +++++++++++--------- src/cmd/gc/walk.c | 6 +++--- src/pkg/runtime/mgc0.c | 2 +- src/pkg/runtime/proc.c | 24 ++++++++++++++++++++++++ src/pkg/runtime/runtime.h | 2 ++ 10 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h index 4a3ec80360..0f46a43166 100644 --- a/src/cmd/dist/a.h +++ b/src/cmd/dist/a.h @@ -101,6 +101,7 @@ void mkzgoarch(char*, char*); void mkzgoos(char*, char*); void mkzruntimedefs(char*, char*); void mkzversion(char*, char*); +void mkzexperiment(char*, char*); // buildgo.c void mkzdefaultcc(char*, char*); diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index f46771d20d..0fe951fc0e 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -557,6 +557,7 @@ static struct { "$GOROOT/pkg/obj/$GOOS_$GOARCH/lib9.a", }}, {"pkg/runtime", { + "zaexperiment.h", // must sort above zasm "zasm_$GOOS_$GOARCH.h", "zsys_$GOOS_$GOARCH.s", "zgoarch_$GOARCH.go", @@ -589,6 +590,7 @@ static struct { {"zgoos_", mkzgoos}, {"zruntime_defs_", mkzruntimedefs}, {"zversion.go", mkzversion}, + {"zaexperiment.h", mkzexperiment}, }; // install installs the library, package, or binary associated with dir, diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c index 62ec8b60e5..e6e309d92a 100644 --- a/src/cmd/dist/buildruntime.c +++ b/src/cmd/dist/buildruntime.c @@ -38,6 +38,34 @@ mkzversion(char *dir, char *file) bfree(&out); } +// mkzexperiment writes zaexperiment.h (sic): +// +// #define GOEXPERIMENT "experiment string" +// +void +mkzexperiment(char *dir, char *file) +{ + Buf b, out, exp; + + USED(dir); + + binit(&b); + binit(&out); + binit(&exp); + + xgetenv(&exp, "GOEXPERIMENT"); + bwritestr(&out, bprintf(&b, + "// auto generated by go tool dist\n" + "\n" + "#define GOEXPERIMENT \"%s\"\n", bstr(&exp))); + + writefile(&out, file, 0); + + bfree(&b); + bfree(&out); + bfree(&exp); +} + // mkzgoarch writes zgoarch_$GOARCH.go: // // package runtime @@ -193,12 +221,13 @@ mkzasm(char *dir, char *file) { int i, n; char *aggr, *p; - Buf in, b, out; + Buf in, b, out, exp; Vec argv, lines, fields; binit(&in); binit(&b); binit(&out); + binit(&exp); vinit(&argv); vinit(&lines); vinit(&fields); @@ -284,6 +313,9 @@ ok: bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB)); } + xgetenv(&exp, "GOEXPERIMENT"); + bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp))); + // Write both to file and to workdir/zasm_GOOS_GOARCH.h. writefile(&out, file, 0); writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0); @@ -291,6 +323,7 @@ ok: bfree(&in); bfree(&b); bfree(&out); + bfree(&exp); vfree(&argv); vfree(&lines); vfree(&fields); diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 59e241bbe3..7704585882 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -982,6 +982,7 @@ EXTERN int noescape; EXTERN int nointerface; EXTERN int fieldtrack_enabled; +EXTERN int precisestack_enabled; /* * y.tab.c diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index f4a6e0503e..414456adf2 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -41,6 +41,7 @@ static struct { } exper[] = { // {"rune32", &rune32}, {"fieldtrack", &fieldtrack_enabled}, + {"precisestack", &precisestack_enabled}, {nil, nil}, }; diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index 0fbac84cf6..7ea76fc5fc 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -316,7 +316,7 @@ walktype(Type *type, Bvec *bv) walktype1(type, &xoffset, bv); } -// Compute a bit vector to describes the pointer containing locations +// Compute a bit vector to describe the pointer-containing locations // in the in and out argument list and dump the bitvector length and // data to the provided symbol. static void @@ -344,9 +344,9 @@ dumpgcargs(Node *fn, Sym *sym) ggloblsym(sym, off, 0, 1); } -// Compute a bit vector to describes the pointer containing locations -// in local variables and dumps the bitvector length and data out to -// the provided symbol. Returns the vector for use and freeing by caller. +// Compute a bit vector to describe the pointer-containing locations +// in local variables and dump the bitvector length and data out to +// the provided symbol. Return the vector for use and freeing by caller. static Bvec* dumpgclocals(Node* fn, Sym *sym) { @@ -438,11 +438,13 @@ allocauto(Prog* ptxt) ll->n->used = 0; markautoused(ptxt); - - // TODO: Remove when liveness analysis sets needzero instead. - for(ll=curfn->dcl; ll != nil; ll=ll->next) - if (ll->n->class == PAUTO) - ll->n->needzero = 1; // ll->n->addrtaken; + + if(precisestack_enabled) { + // TODO: Remove when liveness analysis sets needzero instead. + for(ll=curfn->dcl; ll != nil; ll=ll->next) + if(ll->n->class == PAUTO) + ll->n->needzero = 1; // ll->n->addrtaken; + } listsort(&curfn->dcl, cmpstackvar); diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 489b947143..a1172b87ef 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -2331,9 +2331,9 @@ paramstoheap(Type **argin, int out) v = t->nname; if(v && v->sym && v->sym->name[0] == '~') v = N; - // The garbage collector assumes results are always live, - // so zero them always (1 ||). - if(out && (1 || (v == N && hasdefer))) { + // In precisestack mode, the garbage collector assumes results + // are always live, so zero them always. + if(out && (precisestack_enabled || (v == N && hasdefer))) { // Defer might stop a panic and show the // return values as they exist at the time of panic. // Make sure to zero them on entry to the function. diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 9b6a9d5e96..fe9c18177c 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -1345,7 +1345,7 @@ scaninterfacedata(uintptr bits, byte *scanp, bool afterprologue) Itab *tab; Type *type; - if(afterprologue) { + if(runtime·precisestack && afterprologue) { if(bits == BitsIface) { tab = *(Itab**)scanp; if(tab->type->size <= sizeof(void*) && (tab->type->kind & KindNoPointers)) diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 07515c54f9..e34e9e5067 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -4,6 +4,7 @@ #include "runtime.h" #include "arch_GOARCH.h" +#include "zaexperiment.h" #include "malloc.h" #include "stack.h" #include "race.h" @@ -112,6 +113,7 @@ static void injectglist(G*); static bool preemptall(void); static bool preemptone(P*); static bool exitsyscallfast(void); +static bool haveexperiment(int8*); // The bootstrap sequence is: // @@ -128,6 +130,7 @@ runtime·schedinit(void) byte *p; runtime·sched.maxmcount = 10000; + runtime·precisestack = haveexperiment("precisestack"); m->nomemprof++; runtime·mprofinit(); @@ -2929,3 +2932,24 @@ runtime∕debug·setMaxThreads(intgo in, intgo out) runtime·unlock(&runtime·sched); FLUSH(&out); } + +static int8 experiment[] = GOEXPERIMENT; // defined in zaexperiment.h + +static bool +haveexperiment(int8 *name) +{ + int32 i, j; + + for(i=0; i