]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use funcdata to supply garbage collection information
authorRuss Cox <rsc@golang.org>
Fri, 19 Jul 2013 20:04:09 +0000 (16:04 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 19 Jul 2013 20:04:09 +0000 (16:04 -0400)
This CL introduces a FUNCDATA number for runtime-specific
garbage collection metadata, changes the C and Go compilers
to emit that metadata, and changes the runtime to expect it.

The old pseudo-instructions that carried this information
are gone, as is the linker code to process them.

R=golang-dev, dvyukov, cshapiro
CC=golang-dev
https://golang.org/cl/11406044

28 files changed:
src/cmd/5c/reg.c
src/cmd/5g/peep.c
src/cmd/5g/reg.c
src/cmd/5l/5.out.h
src/cmd/5l/l.h
src/cmd/5l/obj.c
src/cmd/5l/span.c
src/cmd/6c/reg.c
src/cmd/6g/peep.c
src/cmd/6g/reg.c
src/cmd/6l/6.out.h
src/cmd/6l/l.h
src/cmd/6l/obj.c
src/cmd/8c/reg.c
src/cmd/8g/peep.c
src/cmd/8g/reg.c
src/cmd/8l/8.out.h
src/cmd/8l/l.h
src/cmd/8l/obj.c
src/cmd/cc/pgen.c
src/cmd/gc/pgen.c
src/cmd/ld/lib.c
src/pkg/runtime/funcdata.h
src/pkg/runtime/mgc0.c
src/pkg/runtime/runtime.h
src/pkg/runtime/symtab.c
src/pkg/runtime/traceback_arm.c
src/pkg/runtime/traceback_x86.c

index 42c5193de54b3de11e249b787ebb1a6834eb1df1..030b0c327e9cc11a52e65fd9474e61345bcdb1d6 100644 (file)
@@ -112,6 +112,7 @@ regopt(Prog *p)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case AFUNCDATA:
                        continue;
                }
                r = rega();
index 87afa86a8c0d8af3dbe7ff8b5d033356ecd6b98a..c8e8174d36df04b2cc67638279498bd6e66e7543 100644 (file)
@@ -76,10 +76,7 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        p = p->link;
                }
        }
@@ -1196,10 +1193,8 @@ copyu(Prog *p, Adr *v, Adr *s)
                                return 3;
                return 0;
 
-       case ALOCALS:   /* funny */
-       case ANPTRS:
-       case APTRS:
        case APCDATA:
+       case AFUNCDATA:
                return 0;
        }
 }
index e0875995c79a6333d5b03244787f8c81389368c5..0c2898c4c95ab05fd0c470945de1dc03a4720161 100644 (file)
@@ -248,10 +248,7 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        continue;
                }
                r = rega();
index 042017c2a85b0e2ad843e3ea0c871a74d9639927..eda379c6f68f0ed5b0824c5b3d944eafb20e7777 100644 (file)
@@ -201,11 +201,6 @@ enum       as
        AFUNCDATA,
        APCDATA,
 
-       // TODO: Remove these.
-       ALOCALS,
-       ANPTRS,
-       APTRS,
-
        ALAST,
 };
 
index c79bb79e050cc39f53c29fb7af2620167f6c0d38..10d8b5bd3ec1e2d7fb21b91b514cc395c25a3a21 100644 (file)
@@ -154,8 +154,6 @@ struct      Sym
        int32   elfsym;
        int32   locals; // size of stack frame locals area
        int32   args;   // size of stack frame incoming arguments area
-       int32   nptrs;  // number of bits in the pointer map
-       uint32* ptrs;   // pointer map data
        uchar   special;
        uchar   fnptr;  // used as fn ptr
        uchar   stkcheck;
@@ -436,7 +434,6 @@ int32       immaddr(int32);
 int32  opbra(int, int);
 int    brextra(Prog*);
 int    isbranch(Prog*);
-void   fnptrs(void);
 void   doelf(void);
 void   dozerostk(void); // used by -Z
 
index d087bb470c9c09cd3430e00efb4f9151face624f..168cf01de9b1ec99405fa0a919fe6c83e9d10c70 100644 (file)
@@ -615,51 +615,12 @@ loop:
                pc++;
                break;
 
-       case ALOCALS:
-               if(skip)
-                       goto casedef;
-               cursym->locals = p->to.offset;
-               pc++;
-               break;
-
        case ATYPE:
                if(skip)
                        goto casedef;
                pc++;
                goto loop;
 
-       case ANPTRS:
-               if(skip)
-                       goto casedef;
-               if(cursym->nptrs != -1) {
-                       diag("ldobj1: multiple pointer maps defined for %s", cursym->name);
-                       errorexit();
-               }
-               if(p->to.offset > cursym->args/PtrSize) {
-                       diag("ldobj1: pointer map definition for %s exceeds its argument size", cursym->name);
-                       errorexit();
-               }
-               cursym->nptrs = p->to.offset;
-               if(cursym->nptrs != 0)
-                       cursym->ptrs = mal((rnd(cursym->nptrs, 32) / 32) * sizeof(*cursym->ptrs));
-               pc++;
-               goto loop;
-
-       case APTRS:
-               if(skip)
-                       goto casedef;
-               if(cursym->nptrs == -1 || cursym->ptrs == nil) {
-                       diag("ldobj1: pointer map data provided for %s without a definition", cursym->name);
-                       errorexit();
-               }
-               if(p->from.offset*32 >= rnd(cursym->nptrs, 32)) {
-                       diag("ldobj1: excessive pointer map data provided for %s", cursym->name);
-                       errorexit();
-               }
-               cursym->ptrs[p->from.offset] = p->to.offset;
-               pc++;
-               goto loop;
-
        case ATEXT:
                if(cursym != nil && cursym->text) {
                        histtoauto();
@@ -704,7 +665,6 @@ loop:
                s->text = p;
                s->value = pc;
                s->args = p->to.offset2;
-               s->nptrs = -1;
                lastp = p;
                p->pc = pc;
                pc++;
index 96138b26632646564fd0133b1eacdaf7f5d8c023..fe7aface9756f4da629b0bbe5d5181d7823a9bd3 100644 (file)
@@ -830,7 +830,6 @@ buildop(void)
                case ARFE:
                case ATEXT:
                case AUSEFIELD:
-               case ALOCALS:
                case ACASE:
                case ABCASE:
                case ATYPE:
index e40e6c8f0f7791a92b9dfc8a95e82022b799e1ad..edd93a0a068e6c77d1565b6205a72b72a4658a6b 100644 (file)
@@ -111,6 +111,7 @@ regopt(Prog *p)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case AFUNCDATA:
                        continue;
                }
                r = rega();
@@ -645,6 +646,7 @@ brk:
                        case AGLOBL:
                        case ANAME:
                        case ASIGNAME:
+                       case AFUNCDATA:
                                break;
                        }
                }
index 5db9f4cf16cdcde1e9fb6f2e33160c5face3e1d8..fcccea24c40473538b78a8910378f014656331d0 100644 (file)
@@ -132,10 +132,7 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        p = p->link;
                }
        }
index 2cdf5f3e081093a0af71e0b6f671ee04d6508a98..2640a9943360e3946d9a14d5e91cad435ddd1d21 100644 (file)
@@ -223,10 +223,7 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        continue;
                }
                r = rega();
index 5c3e8069703c7668c33d8b09b7bc68230d05e99f..b95b3fd13b5de63172027376cc6d8b5681e918d0 100644 (file)
@@ -766,11 +766,6 @@ enum       as
        AFUNCDATA,
        APCDATA,
        
-       // TODO: Remove these.
-       ALOCALS,
-       ANPTRS,
-       APTRS,
-       
        ALAST
 };
 
index 97676267fc2aa4ab30759c73bd1328ef68c3954f..ab6fcb0785ae52ed8ca302ee3d1d36bd3fff06e7 100644 (file)
@@ -159,10 +159,7 @@ struct     Sym
        int32   got;
        int32   align;  // if non-zero, required alignment in bytes
        int32   elfsym;
-       int32   locals; // size of stack frame locals area
        int32   args;   // size of stack frame incoming arguments area
-       int32   nptrs;  // number of bits in the pointer map
-       uint32* ptrs;   // pointer map data
        Sym*    hash;   // in hash table
        Sym*    allsym; // in all symbol list
        Sym*    next;   // in text or data list
index d2d0459a4e96972d8b3d09dd7a339d3a2f5ed048..c4c743cffd9288112c6776e8993694509a4cf7b0 100644 (file)
@@ -604,51 +604,12 @@ loop:
                pc++;
                goto loop;
 
-       case ALOCALS:
-               if(skip)
-                       goto casdef;
-               cursym->locals = p->to.offset;
-               pc++;
-               goto loop;
-       
        case ATYPE:
                if(skip)
                        goto casdef;
                pc++;
                goto loop;
 
-       case ANPTRS:
-               if(skip)
-                       goto casdef;
-               if(cursym->nptrs != -1) {
-                       diag("ldobj1: multiple pointer maps defined for %s", cursym->name);
-                       errorexit();
-               }
-               if(p->to.offset > cursym->args/PtrSize) {
-                       diag("ldobj1: pointer map definition for %s exceeds its argument size", cursym->name);
-                       errorexit();
-               }
-               cursym->nptrs = p->to.offset;
-               if(cursym->nptrs != 0)
-                       cursym->ptrs = mal((rnd(cursym->nptrs, 32) / 32) * sizeof(*cursym->ptrs));
-               pc++;
-               goto loop;
-
-       case APTRS:
-               if(skip)
-                       goto casdef;
-               if(cursym->nptrs == -1 || cursym->ptrs == nil) {
-                       diag("ldobj1: pointer map data provided for %s without a definition", cursym->name);
-                       errorexit();
-               }
-               if(p->from.offset*32 >= rnd(cursym->nptrs, 32)) {
-                       diag("ldobj1: excessive pointer map data provided for %s", cursym->name);
-                       errorexit();
-               }
-               cursym->ptrs[p->from.offset] = p->to.offset;
-               pc++;
-               goto loop;
-
        case ATEXT:
                s = p->from.sym;
                if(s->text != nil) {
@@ -694,7 +655,6 @@ loop:
                s->hist = gethist();
                s->value = pc;
                s->args = p->to.offset >> 32;
-               s->nptrs = -1;
                lastp = p;
                p->pc = pc++;
                goto loop;
index 6c87d70a5b98ba10fb8418ae81dd42da536f79c0..a3d5d61151c29ab140beb15d77e80b3b96604ec9 100644 (file)
@@ -111,6 +111,7 @@ regopt(Prog *p)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case AFUNCDATA:
                        continue;
                }
                r = rega();
@@ -584,6 +585,7 @@ brk:
                        case AGLOBL:
                        case ANAME:
                        case ASIGNAME:
+                       case AFUNCDATA:
                                break;
                        }
                }
index e4c8afa372d663981bbbf420e88093286b0eb324..fff755cbda841f2f00871878a56b22912704891c 100644 (file)
@@ -126,10 +126,7 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        p = p->link;
                }
        }
index 4a0bf91fbc7591d00797d384f767370a6e9f647d..e8f055f761145e99bd3ec8cba06eadce6c10e583 100644 (file)
@@ -195,10 +195,7 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
-               case ALOCALS:
                case ATYPE:
-               case ANPTRS:
-               case APTRS:
                        continue;
                }
                r = rega();
index fecb0852c8e441474d8a9b395b9f32a5c5e51fb1..7683d50ada5263622db0634983e1313bb2d00a29 100644 (file)
@@ -582,11 +582,6 @@ enum       as
        AFUNCDATA,
        APCDATA,
        
-       // TODO: Remove these.
-       ALOCALS,
-       ANPTRS,
-       APTRS,
-
        ALAST
 };
 
index 2cf8c76b1fc76b81fe88504c1335c3a483077d16..67e607b5bd5ac78221640c870e49e8fd2e51878e 100644 (file)
@@ -143,10 +143,7 @@ struct     Sym
        int32   got;
        int32   align;  // if non-zero, required alignment in bytes
        int32   elfsym;
-       int32   locals; // size of stack frame locals area
        int32   args;   // size of stack frame incoming arguments area
-       int32   nptrs;  // number of bits in the pointer map
-       uint32* ptrs;   // pointer map data
        Sym*    hash;   // in hash table
        Sym*    allsym; // in all symbol list
        Sym*    next;   // in text or data list
index 5e8988c9cb1e908a4da8c0fe196facd94c35d96e..8c84aaaea7352d42cadb2be1c95727859e713e89 100644 (file)
@@ -614,51 +614,12 @@ loop:
                pc++;
                goto loop;
 
-       case ALOCALS:
-               if(skip)
-                       goto casdef;
-               cursym->locals = p->to.offset;
-               pc++;
-               goto loop;
-
        case ATYPE:
                if(skip)
                        goto casdef;
                pc++;
                goto loop;
 
-       case ANPTRS:
-               if(skip)
-                       goto casdef;
-               if(cursym->nptrs != -1) {
-                       diag("ldobj1: multiple pointer maps defined for %s", cursym->name);
-                       errorexit();
-               }
-               if(p->to.offset > cursym->args/PtrSize) {
-                       diag("ldobj1: pointer map definition for %s exceeds its argument size", cursym->name);
-                       errorexit();
-               }
-               cursym->nptrs = p->to.offset;
-               if(cursym->nptrs != 0)
-                       cursym->ptrs = mal((rnd(cursym->nptrs, 32) / 32) * sizeof(*cursym->ptrs));
-               pc++;
-               goto loop;
-
-       case APTRS:
-               if(skip)
-                       goto casdef;
-               if(cursym->nptrs == -1 || cursym->ptrs == nil) {
-                       diag("ldobj1: pointer map data provided for %s without a definition", cursym->name);
-                       errorexit();
-               }
-               if(p->from.offset*32 >= rnd(cursym->nptrs, 32)) {
-                       diag("ldobj1: excessive pointer map data provided for %s", cursym->name);
-                       errorexit();
-               }
-               cursym->ptrs[p->from.offset] = p->to.offset;
-               pc++;
-               goto loop;
-
        case ATEXT:
                s = p->from.sym;
                if(s->text != nil) {
@@ -699,7 +660,6 @@ loop:
                s->hist = gethist();
                s->value = pc;
                s->args = p->to.offset2;
-               s->nptrs = -1;
                lastp = p;
                p->pc = pc++;
                goto loop;
index 8a33898531f481a15ff5efe281b0089a13171331..27022d54e8c4bf979801973c72e05a0caed8a16b 100644 (file)
@@ -77,6 +77,10 @@ codgen(Node *n, Node *nn)
 {
        Prog *sp;
        Node *n1, nod, nod1;
+       Sym *gcsym;
+       static int ngcsym;
+       static char namebuf[40];
+       int32 off;
 
        cursafe = 0;
        curarg = 0;
@@ -97,8 +101,7 @@ codgen(Node *n, Node *nn)
 
        p = gtext(n1->sym, stkoff);
        sp = p;
-       gins(ALOCALS, Z, nodconst(stkoff));
-
+       
        /*
         * isolate first argument
         */
@@ -135,6 +138,34 @@ codgen(Node *n, Node *nn)
        if(thechar=='6' || thechar=='7')        /* [sic] */
                maxargsafe = xround(maxargsafe, 8);
        sp->to.offset += maxargsafe;
+       
+       snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
+       gcsym = slookup(namebuf);
+       gcsym->class = CSTATIC;
+
+       memset(&nod, 0, sizeof nod);
+       nod.op = ONAME;
+       nod.sym = gcsym;
+       nod.class = CSTATIC;
+
+       gins(AFUNCDATA, nodconst(FUNCDATA_GC), &nod);
+
+       // 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.
+       off = 0;
+       gextern(gcsym, nodconst(stkoff), off, 4); // locals
+       off += 4;
+       gextern(gcsym, nodconst(0), off, 4); // nptrs
+       off += 4;
+       gcsym->type = typ(0, T);
+       gcsym->type->width = off;
 }
 
 void
index 4d3859d02d288f4bc0e0d427b92edef00dbf16c7..c25cccdd38bfe08f98b66361a115346b1a8b6ecb 100644 (file)
@@ -6,21 +6,25 @@
 #include       <libc.h>
 #include       "gg.h"
 #include       "opt.h"
+#include       "../../pkg/runtime/funcdata.h"
 
 static void allocauto(Prog* p);
-static void pointermap(Node* fn);
+static int pointermap(Sym*, int, Node*);
+static void gcsymbol(Sym*, Node*);
 
 void
 compile(Node *fn)
 {
        Plist *pl;
-       Node nod1, *n;
-       Prog *plocals, *ptxt, *p, *p1;
+       Node nod1, *n, *gcnod;
+       Prog *pfuncdata, *ptxt, *p, *p1;
        int32 lno;
        Type *t;
        Iter save;
        vlong oldstksize;
        NodeList *l;
+       Sym *gcsym;
+       static int ngcsym;
 
        if(newproc == N) {
                newproc = sysfunc("newproc");
@@ -89,7 +93,13 @@ compile(Node *fn)
 
        ginit();
 
-       plocals = gins(ALOCALS, N, N);
+       snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
+       gcsym = lookup(namebuf);
+       gcnod = newname(gcsym);
+       gcnod->class = PEXTERN;
+
+       nodconst(&nod1, types[TINT32], FUNCDATA_GC);
+       pfuncdata = gins(AFUNCDATA, &nod1, gcnod);
 
        for(t=curfn->paramfld; t; t=t->down)
                gtrack(tracksym(t->type));
@@ -109,8 +119,6 @@ compile(Node *fn)
                }
        }
 
-       pointermap(fn);
-
        genlist(curfn->enter);
 
        retpc = nil;
@@ -151,9 +159,9 @@ compile(Node *fn)
 
        oldstksize = stksize;
        allocauto(ptxt);
-
-       plocals->to.type = D_CONST;
-       plocals->to.offset = stksize;
+       
+       // Emit garbage collection symbol.
+       gcsymbol(gcsym, fn);
 
        if(0)
                print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize);
@@ -171,6 +179,17 @@ ret:
        lineno = lno;
 }
 
+static void
+gcsymbol(Sym *gcsym, Node *fn)
+{
+       int off;
+
+       off = 0;
+       off = duint32(gcsym, off, stksize); // size of local block
+       off = pointermap(gcsym, off, fn); // pointer bitmap for args (must be last)
+       ggloblsym(gcsym, off, 0, 1);
+}
+
 static void
 walktype1(Type *t, vlong *xoffset, Bvec *bv)
 {
@@ -278,12 +297,11 @@ walktype(Type *type, Bvec *bv)
 
 // Compute a bit vector to describes the pointer containing locations
 // in the argument list.
-static void
-pointermap(Node *fn)
+static int
+pointermap(Sym *gcsym, int off, Node *fn)
 {
        Type *thistype, *inargtype, *outargtype;
        Bvec *bv;
-       Prog *prog;
        int32 i;
 
        thistype = getthisx(fn->type);
@@ -296,17 +314,11 @@ pointermap(Node *fn)
                walktype(inargtype, bv);
        if(outargtype != nil)
                walktype(outargtype, bv);
-       prog = gins(ANPTRS, N, N);
-       prog->to.type = D_CONST;
-       prog->to.offset = bv->n;
-       for(i = 0; i < bv->n; i += 32) {
-               prog = gins(APTRS, N, N);
-               prog->from.type = D_CONST;
-               prog->from.offset = i / 32;
-               prog->to.type = D_CONST;
-               prog->to.offset = bv->b[i / 32];
-       }
+       off = duint32(gcsym, off, bv->n);
+       for(i = 0; i < bv->n; i += 32)
+               off = duint32(gcsym, off, bv->b[i/32]);
        free(bv);
+       return off;
 }
 
 // Sort the list of stack variables.  autos after anything else,
index feb84736df9930a02332e97992b709283190cc39..6a299e7f9ab592b1bbaef49d0c6eb47b88b57996 100644 (file)
@@ -2354,7 +2354,7 @@ void
 pclntab(void)
 {
        Prog *p;
-       int32 i, n, nfunc, start, funcstart, nameoff;
+       int32 i, n, nfunc, start, funcstart;
        uint32 *havepc, *havefunc;
        Sym *ftab, *s;
        int32 npcdata, nfuncdata, off, end;
@@ -2409,9 +2409,7 @@ pclntab(void)
                off = setaddr(ftab, off, cursym);
 
                // name int32
-               // Filled in below, after we emit the ptrs.
-               nameoff = off;
-               off += 4;
+               off = setuint32(ftab, off, ftabaddstring(ftab, cursym->name));
                
                // args int32
                // TODO: Move into funcinfo.
@@ -2420,9 +2418,8 @@ pclntab(void)
                else
                        off = setuint32(ftab, off, cursym->args);
 
-               // locals int32
-               // TODO: Move into funcinfo.
-               off = setuint32(ftab, off, cursym->locals);
+               // Dead space. TODO: Delete (and update all parsers).
+               off = setuint32(ftab, off, 0);
        
                // frame int32
                // TODO: Remove entirely. The pcsp table is more precise.
@@ -2435,23 +2432,9 @@ pclntab(void)
                else
                        off = setuint32(ftab, off, (uint32)cursym->text->to.offset+PtrSize);
 
-               // TODO: Move into funcinfo.
-               // ptrsoff, ptrslen int32
-               start = ftab->np;
-               if(start&3) {
-                       diag("bad math in functab: ptrs misaligned");
-                       errorexit();
-               }
-               ftab->size = ftab->np; // for adduint32
-               for(i = 0; i < cursym->nptrs; i += 32)
-                       adduint32(ftab, cursym->ptrs[i/32]);
-               off = setuint32(ftab, off, start);
-               off = setuint32(ftab, off, i/32);
-
-               // Now that ptrs are emitted, can fill in function name.
-               // The string is appended to ftab; we waited until now
-               // to avoid misaligning the ptrs data.
-               setuint32(ftab, nameoff, ftabaddstring(ftab, cursym->name));
+               // Dead space. TODO: Delete (and update all parsers).
+               off = setuint32(ftab, off, 0);
+               off = setuint32(ftab, off, 0);
 
                // pcsp table (offset int32)
                off = addpctab(ftab, off, cursym, "pctospadj", pctospadj, 0);
index 850288bf64c1e360f8954dc4292390831c5039ff..f12bf49fb181257b08445187e3370c4f8f65a71c 100644 (file)
@@ -7,7 +7,9 @@
 // be written using #defines. It is included by the runtime package
 // as well as the compilers.
 
-#define PCDATA_ArgSize 0
+#define PCDATA_ArgSize 0 /* argument size at CALL instruction */
+
+#define FUNCDATA_GC 0 /* garbage collector block */
 
 // To be used in assembly.
 #define ARGSIZE(n) PCDATA $PCDATA_ArgSize, $n
index abf93e425b796a13f97607ac634fbfc543992c22..8654e385442a3da2a72991a2be57c5e0f54a7d38 100644 (file)
@@ -13,6 +13,7 @@
 #include "type.h"
 #include "typekind.h"
 #include "hashmap.h"
+#include "funcdata.h"
 
 enum {
        Debug = 0,
@@ -1385,6 +1386,14 @@ addroot(Obj obj)
 
 extern byte pclntab[]; // base for f->ptrsoff
 
+typedef struct GCFunc GCFunc;
+struct GCFunc
+{
+       uint32  locals; // size of local variables in bytes
+       uint32  nptrs; // number of words that follow
+       uint32  ptrs[1]; // bitmap of pointers in arguments
+};
+
 // Scan a stack frame: local variables and function arguments/results.
 static void
 addframeroots(Stkframe *frame, void*)
@@ -1392,21 +1401,28 @@ addframeroots(Stkframe *frame, void*)
        Func *f;
        byte *ap;
        int32 i, j, nuintptr;
-       uint32 w, b, *ptrs;
+       uint32 w, b;
+       GCFunc *gcf;
 
+       f = frame->fn;
+       gcf = runtime·funcdata(f, FUNCDATA_GC);
+       
        // Scan local variables if stack frame has been allocated.
-       if(frame->varlen > 0)
-               addroot((Obj){frame->varp, frame->varlen, 0});
+       i = frame->varp - (byte*)frame->sp;
+       if(i > 0) {
+               if(gcf == nil)
+                       addroot((Obj){frame->varp - i, i, 0});
+               else if(i >= gcf->locals)
+                       addroot((Obj){frame->varp - gcf->locals, gcf->locals, 0});
+       }
 
        // Scan arguments.
        // Use pointer information if known.
-       f = frame->fn;
-       if(f->args > 0 && f->ptrslen > 0) {
+       if(f->args > 0 && gcf != nil && gcf->nptrs > 0) {
                ap = frame->argp;
                nuintptr = f->args / sizeof(uintptr);
-               ptrs = (uint32*)(pclntab + f->ptrsoff);
-               for(i = 0; i < f->ptrslen; i++) {
-                       w = ptrs[i];
+               for(i = 0; i < gcf->nptrs; i++) {
+                       w = gcf->ptrs[i];
                        b = 1;
                        j = nuintptr;
                        if(j > 32)
@@ -2017,8 +2033,10 @@ runtime·gc(int32 force)
 
        // all done
        m->gcing = 0;
+       m->locks++;
        runtime·semrelease(&runtime·worldsema);
        runtime·starttheworld();
+       m->locks--;
 
        // now that gc is done and we're back on g stack, kick off finalizer thread if needed
        if(finq != nil) {
@@ -2185,8 +2203,10 @@ runtime·ReadMemStats(MStats *stats)
        updatememstats(nil);
        *stats = mstats;
        m->gcing = 0;
+       m->locks++;
        runtime·semrelease(&runtime·worldsema);
        runtime·starttheworld();
+       m->locks--;
 }
 
 void
index 811ec76653d1bce87abbda4975fd15b9cf2683db..f405287aa862c7e77242441266c37f0a074a0ba3 100644 (file)
@@ -407,10 +407,10 @@ struct    Func
        
        // TODO: Remove these fields.
        int32   args;   // in/out args size
-       int32   locals; // locals size
+       int32   x1;     // locals size
        int32   frame;  // legacy frame size; use pcsp if possible
-       int32   ptrsoff;
-       int32   ptrslen;
+       int32   x2;
+       int32   x3;
 
        int32   pcsp;
        int32   pcfile;
@@ -677,10 +677,9 @@ struct Stkframe
        uintptr lr;     // program counter at caller aka link register
        uintptr sp;     // stack pointer at pc
        uintptr fp;     // stack pointer at caller aka frame pointer
+       byte*   varp;           // top of local variables
        byte*   argp;   // pointer to function arguments
        uintptr arglen; // number of bytes at argp
-       byte*   varp;   // pointer to local variables
-       uintptr varlen; // number of bytes at varp
 };
 
 int32  runtime·gentraceback(uintptr, uintptr, uintptr, G*, int32, uintptr*, int32, void(*)(Stkframe*, void*), void*, bool);
@@ -856,6 +855,7 @@ void        runtime·netpollready(G**, PollDesc*, int32);
 void   runtime·crash(void);
 void   runtime·parsedebugvars(void);
 void   _rt0_go(void);
+void*  runtime·funcdata(Func*, int32);
 
 #pragma        varargck        argpos  runtime·printf 1
 #pragma        varargck        type    "c"     int32
index e877a60cd99b24e8d4de44269f4bdd38553ae73f..053e255079ae6732bd540b41e860f1e20a78b137 100644 (file)
@@ -78,17 +78,17 @@ readvarint(byte **pp)
        return v;
 }
 
-static uintptr
-funcdata(Func *f, int32 i)
+void*
+runtime·funcdata(Func *f, int32 i)
 {
        byte *p;
 
        if(i < 0 || i >= f->nfuncdata)
-               return 0;
+               return nil;
        p = (byte*)&f->nfuncdata + 4 + f->npcdata*4;
        if(sizeof(void*) == 8 && ((uintptr)p & 4))
                p += 4;
-       return ((uintptr*)p)[i];
+       return ((void**)p)[i];
 }
 
 static bool
index 5aea699e340ef876e101dcfe3ad74fc89410af05..563ba28c946602fb1fbca1b309c983b32d744000 100644 (file)
@@ -95,7 +95,9 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                                        runtime·throw("unknown caller pc");
                        }
                }
-                       
+
+               frame.varp = (byte*)frame.fp;
+
                // Derive size of arguments.
                // Most functions have a fixed-size argument block,
                // so we can use metadata about the function f.
@@ -121,27 +123,6 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                        }
                }
 
-               // Derive location and size of local variables.
-               if(frame.fp == frame.sp) {
-                       // Function has not created a frame for itself yet.
-                       frame.varp = nil;
-                       frame.varlen = 0;
-               } else if(f->locals == 0) {
-                       // Assume no information, so use whole frame.
-                       // TODO: Distinguish local==0 from local==unknown.
-                       frame.varp = (byte*)frame.sp;
-                       frame.varlen = frame.fp - frame.sp;
-               } else {
-                       if(f->locals > frame.fp - frame.sp) {
-                               runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, runtime·funcname(f));
-                               if(callback != nil)
-                                       runtime·throw("invalid stack");
-                       }
-                       frame.varp = (byte*)frame.fp - f->locals;
-                       frame.varlen = f->locals;
-               }
-
-
                if(skip > 0) {
                        skip--;
                        goto skipped;
@@ -203,7 +184,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                        frame.fn = f = runtime·findfunc(frame.pc);
                        if(f == nil)
                                frame.pc = x;
-                       else if (f->frame == 0)
+                       else if(f->frame == 0)
                                frame.lr = x;
                }
        }
index 3153103d34ee5f03172514b29e628e6186dc6659..b88797210e56801297f579229ffa16056f241832 100644 (file)
@@ -111,6 +111,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                                        runtime·throw("unknown caller pc");
                        }
                }
+               
+               frame.varp = (byte*)frame.fp - sizeof(uintptr);
 
                // Derive size of arguments.
                // Most functions have a fixed-size argument block,
@@ -137,26 +139,6 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
                        }
                }
 
-               // Derive location and size of local variables.
-               if(frame.fp == frame.sp + sizeof(uintptr)) {
-                       // Function has not created a frame for itself yet.
-                       frame.varp = nil;
-                       frame.varlen = 0;
-               } else if(f->locals == 0) {
-                       // Assume no information, so use whole frame.
-                       // TODO: Distinguish local==0 from local==unknown.
-                       frame.varp = (byte*)frame.sp;
-                       frame.varlen = frame.fp - sizeof(uintptr) - frame.sp;
-               } else {
-                       if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) {
-                               runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, runtime·funcname(f));
-                               if(callback != nil)
-                                       runtime·throw("invalid stack");
-                       }
-                       frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->locals;
-                       frame.varlen = f->locals;
-               }
-
                if(skip > 0) {
                        skip--;
                        goto skipped;