]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: get rid of copyable check - all G frames are copyable.
authorKeith Randall <khr@golang.org>
Thu, 11 Sep 2014 20:46:58 +0000 (13:46 -0700)
committerKeith Randall <khr@golang.org>
Thu, 11 Sep 2014 20:46:58 +0000 (13:46 -0700)
Just go ahead and do it, if something is wrong we'll throw.

Also rip out cc-generated arg ptr maps, they are useless now.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/133690045

src/cmd/cc/bv.c [deleted file]
src/cmd/cc/cc.h
src/cmd/cc/pgen.c
src/runtime/stack.c

diff --git a/src/cmd/cc/bv.c b/src/cmd/cc/bv.c
deleted file mode 100644 (file)
index db433de..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include "cc.h"
-
-enum {
-       WORDSIZE = sizeof(uint32),
-       WORDBITS = 32,
-};
-
-uintptr
-bvsize(uintptr n)
-{
-       return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE;
-}
-
-Bvec*
-bvalloc(int32 n)
-{
-       Bvec *bv;
-       uintptr nbytes;
-
-       if(n < 0)
-               fatal(Z, "bvalloc: initial size is negative\n");
-       nbytes = sizeof(Bvec) + bvsize(n);
-       bv = malloc(nbytes);
-       if(bv == nil)
-               fatal(Z, "bvalloc: malloc failed\n");
-       memset(bv, 0, nbytes);
-       bv->n = n;
-       return bv;
-}
-
-void
-bvset(Bvec *bv, int32 i)
-{
-       uint32 mask;
-
-       if(i < 0 || i >= bv->n)
-               fatal(Z, "bvset: index %d is out of bounds with length %d\n", i, bv->n);
-       mask = 1UL << (i % WORDBITS);
-       bv->b[i / WORDBITS] |= mask;
-}
index 1dae5acd90dfc7c9eef5f86154dccece92c04b92..9530f5cf66262edf41df95d46531eb488a53ec3e 100644 (file)
@@ -761,12 +761,6 @@ Bits       blsh(uint);
 int    beq(Bits, Bits);
 int    bset(Bits, uint);
 
-/*
- *     bv.c
- */
-Bvec*  bvalloc(int32 n);
-void   bvset(Bvec *bv, int32 i);
-
 /*
  * dpchk.c
  */
index 4265b1b5ee99820bf1d40daa5860b43b0fd5473c..db9aae916ca6444df9762b0aee9839f0e6f84cce 100644 (file)
 #include "gc.h"
 #include "../../runtime/funcdata.h"
 
-enum { BitsPerPointer = 2 };
-
-static void dumpgcargs(Type *fn, Sym *sym);
-
-static Sym*
-makefuncdatasym(char *namefmt, int64 funcdatakind)
-{
-       Node nod;
-       Sym *sym;
-       static int32 nsym;
-       static char namebuf[40];
-
-       snprint(namebuf, sizeof(namebuf), namefmt, nsym++);
-       sym = slookup(namebuf);
-       sym->class = CSTATIC;
-       memset(&nod, 0, sizeof nod);
-       nod.op = ONAME;
-       nod.sym = sym;
-       nod.class = CSTATIC;
-       gins(AFUNCDATA, nodconst(funcdatakind), &nod);
-       linksym(sym)->type = SRODATA;
-       return sym;
-}
-
 int
 hasdotdotdot(Type *t)
 {
@@ -109,9 +85,6 @@ codgen(Node *n, Node *nn)
 {
        Prog *sp;
        Node *n1, nod, nod1;
-       Sym *gcargs;
-       Sym *gclocals;
-       int isvarargs;
 
        cursafe = 0;
        curarg = 0;
@@ -134,16 +107,6 @@ codgen(Node *n, Node *nn)
        p->from.sym->cfunc = 1;
        sp = p;
 
-       /*
-        * generate funcdata symbol for this function.
-        * data is filled in at the end of codgen().
-        */
-       isvarargs = hasdotdotdot(thisfn);
-       gcargs = nil;
-       if(!isvarargs)
-               gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
-       gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
-
        /*
         * isolate first argument
         */
@@ -178,22 +141,6 @@ codgen(Node *n, Node *nn)
        if(thechar=='6' || thechar=='7')        /* [sic] */
                maxargsafe = xround(maxargsafe, 8);
        sp->to.offset += maxargsafe;
-
-       if(!isvarargs)
-               dumpgcargs(thisfn, gcargs);
-
-       // TODO(rsc): "stkoff" is not right. It does not account for
-       // the possibility of data stored in .safe variables.
-       // Unfortunately those move up and down just like
-       // the argument frame (and in fact dovetail with it)
-       // so the number we need is not available or even
-       // well-defined. Probably we need to make the safe
-       // area its own section.
-       // That said, we've been using stkoff for months
-       // and nothing too terrible has happened.
-       gextern(gclocals, nodconst(-stkoff), 0, 4); // locals
-       gclocals->type = typ(0, T);
-       gclocals->type->width = 4;
 }
 
 void
@@ -673,113 +620,3 @@ bcomplex(Node *n, Node *c)
        boolgen(n, 1, Z);
        return 0;
 }
-
-// Updates the bitvector with a set bit for each pointer containing
-// value in the type description starting at offset.
-static void
-walktype1(Type *t, int32 offset, Bvec *bv, int param)
-{
-       Type *t1;
-       int32 o;
-       int32 widthptr;
-
-       widthptr = ewidth[TIND];
-       switch(t->etype) {
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TFLOAT:
-       case TDOUBLE:
-               // non-pointer types
-               for(o = 0; o < t->width; o++)
-                       bvset(bv, ((offset + t->offset + o) / widthptr) * BitsPerPointer); // 1 = live scalar
-               break;
-
-       case TIND:
-       pointer:
-               // pointer types
-               if((offset + t->offset) % widthptr != 0)
-                       yyerror("unaligned pointer");
-               bvset(bv, ((offset + t->offset) / widthptr)*BitsPerPointer + 1); // 2 = live ptr
-               break;
-
-       case TARRAY:
-               if(param)       // unlike Go, C passes arrays by reference
-                       goto pointer;
-               // array in struct or union is an actual array
-               for(o = 0; o < t->width; o += t->link->width)
-                       walktype1(t->link, offset+o, bv, 0);
-               break;
-
-       case TSTRUCT:
-               // build map recursively
-               for(t1 = t->link; t1 != T; t1 = t1->down)
-                       walktype1(t1, offset, bv, 0);
-               break;
-
-       case TUNION:
-               walktype1(t->link, offset, bv, 0);
-               break;
-
-       default:
-               yyerror("can't handle arg type %s\n", tnames[t->etype]);
-       }
-}
-
-// Compute a bit vector to describe the pointer containing locations
-// in the argument list.  Adds the data to gcsym and returns the offset
-// of end of the bit vector.
-static void
-dumpgcargs(Type *fn, Sym *sym)
-{
-       Bvec *bv;
-       Type *t;
-       int32 i;
-       int32 argbytes;
-       int32 symoffset, argoffset;
-
-       // Dump the length of the bitmap array.  This value is always one for
-       // functions written in C.
-       symoffset = 0;
-       gextern(sym, nodconst(1), symoffset, 4);
-       symoffset += 4;
-       argbytes = (argsize(1) + ewidth[TIND] - 1);
-       bv = bvalloc((argbytes  / ewidth[TIND]) * BitsPerPointer);
-       argoffset = 0;
-       if(hasdotdotdot(thisfn))
-               argoffset = align(0, fn->link, Aarg0, nil);
-       if(argoffset > 0) {
-               // The C calling convention returns structs by copying them to a
-               // location pointed to by a hidden first argument.  This first
-               // argument is a pointer.
-               if(argoffset != ewidth[TIND])
-                       yyerror("passbyptr arg not the right size");
-               bvset(bv, 1); // 2 = live ptr
-       }
-       for(t = fn->down; t != T; t = t->down) {
-               if(t->etype == TVOID)
-                       continue;
-               argoffset = align(argoffset, t, Aarg1, nil);
-               walktype1(t, argoffset, bv, 1);
-               argoffset = align(argoffset, t, Aarg2, nil);
-       }
-       // Dump the length of the bitmap.
-       gextern(sym, nodconst(bv->n), symoffset, 4);
-       symoffset += 4;
-       // Dump the words of the bitmap.
-       for(i = 0; i < bv->n; i += 32) {
-               gextern(sym, nodconst(bv->b[i/32]), symoffset, 4);
-               symoffset += 4;
-       }
-       free(bv);
-       // Finalize the gc symbol.
-       sym->type = typ(0, T);
-       sym->type->width = symoffset;
-}
index 2e0c91de0817105a4d45f018bc70291e153ff488..cc2857ac81a41bd5f7a3f1eb962edb4830abf8c0 100644 (file)
@@ -331,145 +331,22 @@ mapnames[] = {
 // |  args to callee  |
 // +------------------+ <- frame->sp
 //
-// (arm: TODO)
-
-typedef struct CopyableInfo CopyableInfo;
-struct CopyableInfo {
-       Stack stk;
-       int32 frames;   // count of copyable frames (-1 = not copyable)
-};
+// (arm)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// | caller's retaddr |
+// +------------------+ <- frame->varp
+// |     locals       |
+// +------------------+
+// |  args to callee  |
+// +------------------+
+// |  return address  |
+// +------------------+ <- frame->sp
 
 void runtime·main(void);
 void runtime·switchtoM(void(*)(void));
 
-static bool
-checkframecopy(Stkframe *frame, void *arg)
-{
-       CopyableInfo *cinfo;
-       Func *f;
-       StackMap *stackmap;
-
-       cinfo = arg;
-       f = frame->fn;
-       if(StackDebug >= 2)
-               runtime·printf("    checking %s frame=[%p,%p] stk=[%p,%p]\n", runtime·funcname(f), frame->sp, frame->fp, cinfo->stk.lo, cinfo->stk.hi);
-       // if we're not in the segment any more, return immediately.
-       if(frame->varp < cinfo->stk.lo || frame->varp >= cinfo->stk.hi) {
-               if(StackDebug >= 2)
-                       runtime·printf("    <next segment>\n");
-               return false; // stop traceback
-       }
-       if(f->entry == (uintptr)runtime·switchtoM) {
-               // A special routine at the bottom of stack of a goroutine that does onM call.
-               // We will allow it to be copied even though we don't
-               // have full GC info for it (because it is written in asm).
-               cinfo->frames++;
-               return true;
-       }
-       if((byte*)frame->varp != (byte*)frame->sp) { // not in prologue (and has at least one local or outarg)
-               stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-               if(stackmap == nil) {
-                       cinfo->frames = -1;
-                       runtime·printf("runtime: copystack: no locals info for %s\n", runtime·funcname(f));
-                       return false;
-               }
-               if(stackmap->n <= 0) {
-                       cinfo->frames = -1;
-                       runtime·printf("runtime: copystack: locals size info only for %s\n", runtime·funcname(f));
-                       return false;
-               }
-       }
-       if(frame->arglen != 0) {
-               stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
-               if(stackmap == nil) {
-                       cinfo->frames = -1;
-                       runtime·printf("runtime: copystack: no arg info for %s\n", runtime·funcname(f));
-                       return false;
-               }
-       }
-       cinfo->frames++;
-       return true; // this frame is ok; keep going
-}
-
-// If the top segment of the stack contains an uncopyable
-// frame, return -1.  Otherwise return the number of frames
-// in the top segment, all of which are copyable.
-static int32
-copyabletopsegment(G *gp)
-{
-       CopyableInfo cinfo;
-       Defer *d;
-       Func *f;
-       FuncVal *fn;
-       StackMap *stackmap;
-       bool (*cb)(Stkframe*, void*);
-
-       if(gp->stack.lo == 0)
-               runtime·throw("missing stack in copyabletopsegment");
-       cinfo.stk = gp->stack;
-       cinfo.frames = 0;
-
-       // Check that each frame is copyable.  As a side effect,
-       // count the frames.
-       cb = checkframecopy;
-       runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &cb, &cinfo, false);
-       if(StackDebug >= 1 && cinfo.frames != -1)
-               runtime·printf("copystack: %d copyable frames\n", cinfo.frames);
-
-       if(cinfo.frames == -1)
-               return -1;
-
-       // Check to make sure all Defers are copyable
-       for(d = gp->defer; d != nil; d = d->link) {
-               if(cinfo.stk.lo <= (uintptr)d && (uintptr)d < cinfo.stk.hi) {
-                       // Defer is on the stack.  Its copyableness has
-                       // been established during stack walking.
-                       // For now, this only happens with the Defer in runtime.main.
-                       continue;
-               }
-               if(d->argp < cinfo.stk.lo || cinfo.stk.hi <= d->argp)
-                       break; // a defer for the next segment
-               fn = d->fn;
-               if(fn == nil) // See issue 8047
-                       continue;
-               f = runtime·findfunc((uintptr)fn->fn);
-               if(f == nil) {
-                       runtime·printf("runtime: copystack: no func for deferred pc %p\n", fn->fn);
-                       return -1;
-               }
-
-               // Check to make sure we have an args pointer map for the defer's args.
-               // We only need the args map, but we check
-               // for the locals map also, because when the locals map
-               // isn't provided it means the ptr map came from C and
-               // C (particularly, cgo) lies to us.  See issue 7695.
-               stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
-               if(stackmap == nil || stackmap->n <= 0) {
-                       runtime·printf("runtime: copystack: no arg info for deferred %s\n", runtime·funcname(f));
-                       return -1;
-               }
-               stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-               if(stackmap == nil || stackmap->n <= 0) {
-                       runtime·printf("runtime: copystack: no local info for deferred %s\n", runtime·funcname(f));
-                       return -1;
-               }
-
-               if(cinfo.stk.lo <= (uintptr)fn && (uintptr)fn < cinfo.stk.hi) {
-                       // FuncVal is on the stack.  Again, its copyableness
-                       // was established during stack walking.
-                       continue;
-               }
-               // The FuncVal may have pointers in it, but fortunately for us
-               // the compiler won't put pointers into the stack in a
-               // heap-allocated FuncVal.
-               // One day if we do need to check this, we'll need maps of the
-               // pointerness of the closure args.  The only place we have that map
-               // right now is in the gc program for the FuncVal.  Ugh.
-       }
-
-       return cinfo.frames;
-}
-
 typedef struct AdjustInfo AdjustInfo;
 struct AdjustInfo {
        Stack old;
@@ -573,8 +450,12 @@ adjustframe(Stkframe *frame, void *arg)
        f = frame->fn;
        if(StackDebug >= 2)
                runtime·printf("    adjusting %s frame=[%p,%p] pc=%p continpc=%p\n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc);
-       if(f->entry == (uintptr)runtime·switchtoM)
+       if(f->entry == (uintptr)runtime·switchtoM) {
+               // A special routine at the bottom of stack of a goroutine that does an onM call.
+               // We will allow it to be copied even though we don't
+               // have full GC info for it (because it is written in asm).
                return true;
+       }
        targetpc = frame->continpc;
        if(targetpc == 0) {
                // Frame is dead.
@@ -648,11 +529,10 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
                        runtime·printf("runtime: adjustdefers argp=%p stk=%p %p\n", d->argp, adjinfo->old.lo, adjinfo->old.hi);
                        runtime·throw("adjustdefers: unexpected argp");
                }
+               d->argp += adjinfo->delta;
                fn = d->fn;
                if(fn == nil) {
-                       // Defer of nil function.  It will panic when run, and there
-                       // aren't any args to adjust.  See issue 8047.
-                       d->argp += adjinfo->delta;
+                       // Defer of nil function.  It will panic when run.  See issue 8047.
                        continue;
                }
                f = runtime·findfunc((uintptr)fn->fn);
@@ -675,7 +555,11 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
                        bv = runtime·stackmapdata(stackmap, 0);
                        adjustpointers(d->args, &bv, adjinfo, f);
                }
-               d->argp += adjinfo->delta;
+               // The FuncVal may have pointers in it, but fortunately for us
+               // the compiler won't put pointers into the stack in a
+               // heap-allocated FuncVal.
+               // One day if we do need to check this, we can use the gc bits in the
+               // heap to do the right thing (although getting the size will be expensive).
        }
 }
 
@@ -707,10 +591,9 @@ adjustsudogs(G *gp, AdjustInfo *adjinfo)
        }
 }
 
-// Copies the top stack segment of gp to a new stack segment of a
-// different size.  The top segment must contain nframes frames.
+// Copies gp's stack to a new stack of a different size.
 static void
-copystack(G *gp, uintptr nframes, uintptr newsize)
+copystack(G *gp, uintptr newsize)
 {
        Stack old, new;
        uintptr used;
@@ -735,7 +618,7 @@ copystack(G *gp, uintptr nframes, uintptr newsize)
        adjinfo.old = old;
        adjinfo.delta = new.hi - old.hi;
        cb = adjustframe;
-       runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, &cb, &adjinfo, false);
+       runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &cb, &adjinfo, false);
        
        // adjust other miscellaneous things that have pointers into stacks.
        adjustctxt(gp, &adjinfo);
@@ -785,7 +668,7 @@ runtime·round2(int32 x)
 void
 runtime·newstack(void)
 {
-       int32 oldsize, newsize, nframes;
+       int32 oldsize, newsize;
        uintptr sp;
        G *gp;
        Gobuf morebuf;
@@ -867,10 +750,6 @@ runtime·newstack(void)
        }
 
        // Allocate a bigger segment and move the stack.
-       nframes = copyabletopsegment(gp);
-       if(nframes == -1)
-               runtime·throw("unable to grow stack");
-       
        oldsize = gp->stack.hi - gp->stack.lo;
        newsize = oldsize * 2;
        if(newsize > runtime·maxstacksize) {
@@ -880,7 +759,7 @@ runtime·newstack(void)
 
        // Note that the concurrent GC might be scanning the stack as we try to replace it.
        // copystack takes care of the appropriate coordination with the stack scanner.
-       copystack(gp, nframes, newsize);
+       copystack(gp, newsize);
        if(StackDebug >= 1)
                runtime·printf("stack grow done\n");
        runtime·casgstatus(gp, Gwaiting, Grunning);
@@ -913,14 +792,13 @@ runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv)
 void
 runtime·shrinkstack(G *gp)
 {
-       int32 nframes;
        uintptr used, oldsize, newsize;
 
        if(runtime·readgstatus(gp) == Gdead)
                return;
        if(gp->stack.lo == 0)
                runtime·throw("missing stack in shrinkstack");
-       //return; // TODO: why does this happen?
+
        oldsize = gp->stack.hi - gp->stack.lo;
        newsize = oldsize / 2;
        if(newsize < FixedStack)
@@ -938,10 +816,7 @@ runtime·shrinkstack(G *gp)
 #endif
        if(StackDebug > 0)
                runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uint64)newsize);
-       nframes = copyabletopsegment(gp);
-       if(nframes == -1)
-               return;
-       copystack(gp, nframes, newsize);
+       copystack(gp, newsize);
 }
 
 static void badc(void);