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
void mkzgoos(char*, char*);
void mkzruntimedefs(char*, char*);
void mkzversion(char*, char*);
+void mkzexperiment(char*, char*);
// buildgo.c
void mkzdefaultcc(char*, char*);
"$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",
{"zgoos_", mkzgoos},
{"zruntime_defs_", mkzruntimedefs},
{"zversion.go", mkzversion},
+ {"zaexperiment.h", mkzexperiment},
};
// install installs the library, package, or binary associated with dir,
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
{
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);
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);
bfree(&in);
bfree(&b);
bfree(&out);
+ bfree(&exp);
vfree(&argv);
vfree(&lines);
vfree(&fields);
EXTERN int nointerface;
EXTERN int fieldtrack_enabled;
+EXTERN int precisestack_enabled;
/*
* y.tab.c
} exper[] = {
// {"rune32", &rune32},
{"fieldtrack", &fieldtrack_enabled},
+ {"precisestack", &precisestack_enabled},
{nil, nil},
};
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
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)
{
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);
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.
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))
#include "runtime.h"
#include "arch_GOARCH.h"
+#include "zaexperiment.h"
#include "malloc.h"
#include "stack.h"
#include "race.h"
static bool preemptall(void);
static bool preemptone(P*);
static bool exitsyscallfast(void);
+static bool haveexperiment(int8*);
// The bootstrap sequence is:
//
byte *p;
runtime·sched.maxmcount = 10000;
+ runtime·precisestack = haveexperiment("precisestack");
m->nomemprof++;
runtime·mprofinit();
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<sizeof(experiment); i++) {
+ if((i == 0 || experiment[i-1] == ',') && experiment[i] == name[0]) {
+ for(j=0; name[j]; j++)
+ if(experiment[i+j] != name[j])
+ goto nomatch;
+ if(experiment[i+j] != '\0' && experiment[i+j] != ',')
+ goto nomatch;
+ return 1;
+ }
+ nomatch:;
+ }
+ return 0;
+}
int32 scheddetail;
};
+extern bool runtime·precisestack;
+
/*
* defined macros
* you need super-gopher-guru privilege