]> Cypherpunks repositories - gostls13.git/commitdiff
ld: 25% faster
authorRuss Cox <rsc@golang.org>
Sat, 9 Apr 2011 13:44:20 +0000 (09:44 -0400)
committerRuss Cox <rsc@golang.org>
Sat, 9 Apr 2011 13:44:20 +0000 (09:44 -0400)
The ld time was dominated by symbol table processing, so
  * increase hash table size
  * emit fewer symbols in gc (just 1 per string, 1 per type)
  * add read-only lookup to avoid creating spurious symbols
  * add linked list to speed whole-table traversals

Breaks dwarf generator (no idea why), so disable dwarf.

Reduces time for 6l to link godoc by 25%.

R=ken2
CC=golang-dev
https://golang.org/cl/4383047

20 files changed:
src/cmd/5g/gobj.c
src/cmd/5l/l.h
src/cmd/6g/gobj.c
src/cmd/6l/asm.c
src/cmd/6l/l.h
src/cmd/6l/obj.c
src/cmd/8g/gobj.c
src/cmd/8l/l.h
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/obj.c
src/cmd/gc/reflect.c
src/cmd/ld/data.c
src/cmd/ld/dwarf.c
src/cmd/ld/elf.c
src/cmd/ld/go.c
src/cmd/ld/lib.c
src/cmd/ld/lib.h
src/cmd/ld/pe.c
src/cmd/ld/symtab.c

index bf59534b9bd0200c4b8f59b870608d8dbbc9bc27..acece6c0ddef7f556772066a923677209d66f055 100644 (file)
@@ -268,7 +268,7 @@ static Prog *estrdat;
 static int gflag;
 static Prog *savepc;
 
-static void
+void
 data(void)
 {
        gflag = debug['g'];
@@ -285,7 +285,7 @@ data(void)
        pc = estrdat;
 }
 
-static void
+void
 text(void)
 {
        if(!savepc)
@@ -310,6 +310,29 @@ dumpdata(void)
        pc = estrdat;
 }
 
+int
+dsname(Sym *sym, int off, char *t, int n)
+{
+       Prog *p;
+
+       p = gins(ADATA, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.etype = TINT32;
+       p->from.offset = off;
+       p->from.reg = NREG;
+       p->from.sym = sym;
+       
+       p->reg = n;
+       
+       p->to.type = D_SCONST;
+       p->to.name = D_NONE;
+       p->to.reg = NREG;
+       p->to.offset = 0;
+       memmove(p->to.sval, t, n);
+       return off + n;
+}
+
 /*
  * make a refer to the data s, s+len
  * emitting DATA if needed.
@@ -317,76 +340,15 @@ dumpdata(void)
 void
 datastring(char *s, int len, Addr *a)
 {
-       int w;
-       Prog *p;
-       Addr ac, ao;
-       static int gen;
-       struct {
-               Strlit lit;
-               char buf[100];
-       } tmp;
-
-       // string
-       memset(&ao, 0, sizeof(ao));
-       ao.type = D_OREG;
-       ao.name = D_STATIC;
-       ao.etype = TINT32;
-       ao.offset = 0;          // fill in
-       ao.reg = NREG;
-
-       // constant
-       memset(&ac, 0, sizeof(ac));
-       ac.type = D_CONST;
-       ac.name = D_NONE;
-       ac.offset = 0;          // fill in
-       ac.reg = NREG;
-
-       // huge strings are made static to avoid long names.
-       if(len > 100) {
-               snprint(namebuf, sizeof(namebuf), ".string.%d", gen++);
-               ao.sym = lookup(namebuf);
-               ao.name = D_STATIC;
-       } else {
-               if(len > 0 && s[len-1] == '\0')
-                       len--;
-               tmp.lit.len = len;
-               memmove(tmp.lit.s, s, len);
-               tmp.lit.s[len] = '\0';
-               len++;
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
-               ao.sym = pkglookup(namebuf, stringpkg);
-               ao.name = D_EXTERN;
-       }
-       *a = ao;
-
-       // only generate data the first time.
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       for(w=0; w<len; w+=8) {
-               p = pc;
-               gins(ADATA, N, N);
-
-               // DATA s+w, [NSNAME], $"xxx"
-               p->from = ao;
-               p->from.offset = w;
-
-               p->reg = NSNAME;
-               if(w+8 > len)
-                       p->reg = len-w;
-
-               p->to = ac;
-               p->to.type = D_SCONST;
-               p->to.offset = len;
-               memmove(p->to.sval, s+w, p->reg);
-       }
-       p = pc;
-       ggloblsym(ao.sym, len, ao.name == D_EXTERN);
-       if(ao.name == D_STATIC)
-               p->from.name = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(s, len);
+       a->type = D_OREG;
+       a->name = D_EXTERN;
+       a->etype = TINT32;
+       a->offset = widthptr+4;  // skip header
+       a->reg = NREG;
+       a->sym = sym;
 }
 
 /*
@@ -396,77 +358,15 @@ datastring(char *s, int len, Addr *a)
 void
 datagostring(Strlit *sval, Addr *a)
 {
-       Prog *p;
-       Addr ac, ao, ap;
-       int32 wi, wp;
-       static int gen;
-
-       memset(&ac, 0, sizeof(ac));
-       memset(&ao, 0, sizeof(ao));
-       memset(&ap, 0, sizeof(ap));
-
-       // constant
-       ac.type = D_CONST;
-       ac.name = D_NONE;
-       ac.offset = 0;                  // fill in
-       ac.reg = NREG;
-
-       // string len+ptr
-       ao.type = D_OREG;
-       ao.name = D_STATIC;             // fill in
-       ao.etype = TINT32;
-       ao.sym = nil;                   // fill in
-       ao.reg = NREG;
-
-       // $string len+ptr
-       datastring(sval->s, sval->len, &ap);
-       ap.type = D_CONST;
-       ap.etype = TINT32;
-
-       wi = types[TUINT32]->width;
-       wp = types[tptr]->width;
-
-       if(ap.name == D_STATIC) {
-               // huge strings are made static to avoid long names
-               snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
-               ao.sym = lookup(namebuf);
-               ao.name = D_STATIC;
-       } else {
-               // small strings get named by their contents,
-               // so that multiple modules using the same string
-               // can share it.
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval);
-               ao.sym = pkglookup(namebuf, gostringpkg);
-               ao.name = D_EXTERN;
-       }
-
-       *a = ao;
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       // DATA gostring, wp, $cstring
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->reg = wp;
-       p->to = ap;
-
-       // DATA gostring+wp, wi, $len
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->from.offset = wp;
-       p->reg = wi;
-       p->to = ac;
-       p->to.offset = sval->len;
-
-       p = pc;
-       ggloblsym(ao.sym, types[TSTRING]->width, ao.name == D_EXTERN);
-       if(ao.name == D_STATIC)
-               p->from.name = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(sval->s, sval->len);
+       a->type = D_OREG;
+       a->name = D_EXTERN;
+       a->etype = TINT32;
+       a->offset = 0;  // header
+       a->reg = NREG;
+       a->sym = sym;
 }
 
 void
index 9ce9d02c6c387b9be0a3823869053ee89bb2f6d8..cf5a9990b93452c534c85139787b4904062d88e9 100644 (file)
@@ -148,6 +148,7 @@ struct      Sym
        uchar   foreign;        // called by arm if thumb, by thumb if arm
        uchar   fnptr;  // used as fn ptr
        Sym*    hash;   // in hash table
+       Sym*    allsym; // in all symbol list
        Sym*    next;   // in text or data list
        Sym*    sub;    // in SSUB list
        Sym*    outer;  // container of sub
@@ -265,7 +266,6 @@ enum
        LEAF            = 1<<2,
 
        STRINGSZ        = 200,
-       NHASH           = 10007,
        MINSIZ          = 64,
        NENT            = 100,
        MAXIO           = 8192,
index b667ae48a220707b3ad700d25573fb2ca536b4ab..507764a3bc9f0681d6fc4218ee5e9ed6e3153f6b 100644 (file)
@@ -280,7 +280,7 @@ static Prog *estrdat;
 static int gflag;
 static Prog *savepc;
 
-static void
+void
 data(void)
 {
        gflag = debug['g'];
@@ -297,7 +297,7 @@ data(void)
        pc = estrdat;
 }
 
-static void
+void
 text(void)
 {
        if(!savepc)
@@ -322,6 +322,24 @@ dumpdata(void)
        pc = estrdat;
 }
 
+int
+dsname(Sym *s, int off, char *t, int n)
+{
+       Prog *p;
+
+       p = gins(ADATA, N, N);
+       p->from.type = D_EXTERN;
+       p->from.index = D_NONE;
+       p->from.offset = off;
+       p->from.scale = n;
+       p->from.sym = s;
+       
+       p->to.type = D_SCONST;
+       p->to.index = D_NONE;
+       memmove(p->to.sval, t, n);
+       return off + n;
+}
+
 /*
  * make a refer to the data s, s+len
  * emitting DATA if needed.
@@ -329,74 +347,13 @@ dumpdata(void)
 void
 datastring(char *s, int len, Addr *a)
 {
-       int w;
-       Prog *p;
-       Addr ac, ao;
-       static int gen;
-       struct {
-               Strlit lit;
-               char buf[100];
-       } tmp;
-
-       // string
-       memset(&ao, 0, sizeof(ao));
-       ao.type = D_STATIC;
-       ao.index = D_NONE;
-       ao.etype = TINT32;
-       ao.offset = 0;          // fill in
-
-       // constant
-       memset(&ac, 0, sizeof(ac));
-       ac.type = D_CONST;
-       ac.index = D_NONE;
-       ac.offset = 0;          // fill in
-
-       // huge strings are made static to avoid long names.
-       if(len > 100) {
-               snprint(namebuf, sizeof(namebuf), ".string.%d", gen++);
-               ao.sym = lookup(namebuf);
-               ao.type = D_STATIC;
-       } else {
-               if(len > 0 && s[len-1] == '\0')
-                       len--;
-               tmp.lit.len = len;
-               memmove(tmp.lit.s, s, len);
-               tmp.lit.s[len] = '\0';
-               len++;
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
-               ao.sym = pkglookup(namebuf, stringpkg);
-               ao.type = D_EXTERN;
-       }
-       *a = ao;
-
-       // only generate data the first time.
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       for(w=0; w<len; w+=8) {
-               p = pc;
-               gins(ADATA, N, N);
-
-               // DATA s+w, [NSNAME], $"xxx"
-               p->from = ao;
-               p->from.offset = w;
-
-               p->from.scale = NSNAME;
-               if(w+8 > len)
-                       p->from.scale = len-w;
-
-               p->to = ac;
-               p->to.type = D_SCONST;
-               p->to.offset = len;
-               memmove(p->to.sval, s+w, p->from.scale);
-       }
-       p = pc;
-       ggloblsym(ao.sym, len, ao.type == D_EXTERN);
-       if(ao.type == D_STATIC)
-               p->from.type = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(s, len);
+       a->type = D_EXTERN;
+       a->sym = sym;
+       a->offset = widthptr+4;  // skip header
+       a->etype = TINT32;
 }
 
 /*
@@ -406,76 +363,13 @@ datastring(char *s, int len, Addr *a)
 void
 datagostring(Strlit *sval, Addr *a)
 {
-       Prog *p;
-       Addr ac, ao, ap;
-       int32 wi, wp;
-       static int gen;
-
-       memset(&ac, 0, sizeof(ac));
-       memset(&ao, 0, sizeof(ao));
-       memset(&ap, 0, sizeof(ap));
-
-       // constant
-       ac.type = D_CONST;
-       ac.index = D_NONE;
-       ac.offset = 0;                  // fill in
-
-       // string len+ptr
-       ao.type = D_STATIC;             // fill in
-       ao.index = D_NONE;
-       ao.etype = TINT32;
-       ao.sym = nil;                   // fill in
-
-       // $string len+ptr
-       datastring(sval->s, sval->len, &ap);
-       ap.index = ap.type;
-       ap.type = D_ADDR;
-       ap.etype = TINT32;
-
-       wi = types[TUINT32]->width;
-       wp = types[tptr]->width;
-
-       if(ap.index == D_STATIC) {
-               // huge strings are made static to avoid long names
-               snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
-               ao.sym = lookup(namebuf);
-               ao.type = D_STATIC;
-       } else {
-               // small strings get named by their contents,
-               // so that multiple modules using the same string
-               // can share it.
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval);
-               ao.sym = pkglookup(namebuf, gostringpkg);
-               ao.type = D_EXTERN;
-       }
-
-       *a = ao;
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       // DATA gostring, wp, $cstring
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->from.scale = wp;
-       p->to = ap;
-
-       // DATA gostring+wp, wi, $len
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->from.offset = wp;
-       p->from.scale = wi;
-       p->to = ac;
-       p->to.offset = sval->len;
-
-       p = pc;
-       ggloblsym(ao.sym, types[TSTRING]->width, ao.type == D_EXTERN);
-       if(ao.type == D_STATIC)
-               p->from.type = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(sval->s, sval->len);
+       a->type = D_EXTERN;
+       a->sym = sym;
+       a->offset = 0;  // header
+       a->etype = TINT32;
 }
 
 void
index 3e2fe69604e9e6d1147c73b419c4a21ad2e9347b..ba2074fde0a1de79e52fb3796a772cc9102c9171 100644 (file)
@@ -1101,37 +1101,34 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
 {
        Auto *a;
        Sym *s;
-       int h;
 
-       for(h=0; h<NHASH; h++) {
-               for(s=hash[h]; s!=S; s=s->hash) {
-                       if(s->hide)
-                               continue;
-                       switch(s->type&~SSUB) {
-                       case SCONST:
-                       case SRODATA:
-                       case SDATA:
-                       case SELFDATA:
-                       case SMACHOGOT:
-                       case STYPE:
-                       case SSTRING:
-                       case SGOSTRING:
-                       case SWINDOWS:
-                               if(!s->reachable)
-                                       continue;
-                               put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
+       for(s=allsym; s!=S; s=s->allsym) {
+               if(s->hide)
+                       continue;
+               switch(s->type&~SSUB) {
+               case SCONST:
+               case SRODATA:
+               case SDATA:
+               case SELFDATA:
+               case SMACHOGOT:
+               case STYPE:
+               case SSTRING:
+               case SGOSTRING:
+               case SWINDOWS:
+                       if(!s->reachable)
                                continue;
+                       put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
+                       continue;
 
-                       case SBSS:
-                               if(!s->reachable)
-                                       continue;
-                               put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
+               case SBSS:
+                       if(!s->reachable)
                                continue;
+                       put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
+                       continue;
 
-                       case SFILE:
-                               put(nil, s->name, 'f', s->value, 0, s->version, 0);
-                               continue;
-                       }
+               case SFILE:
+                       put(nil, s->name, 'f', s->value, 0, s->version, 0);
+                       continue;
                }
        }
 
index 139b06af8926d59303c84c9846ff66de894a8a2b..4fc13b94ae00789ad626197791a637f9fa6f7040 100644 (file)
@@ -138,6 +138,7 @@ struct      Sym
        int32   plt;
        int32   got;
        Sym*    hash;   // in hash table
+       Sym*    allsym; // in all symbol list
        Sym*    next;   // in text or data list
        Sym*    sub;    // in SSUB list
        Sym*    outer;  // container of sub
@@ -178,7 +179,6 @@ struct      Movtab
 
 enum
 {
-       NHASH           = 10007,
        MINSIZ          = 8,
        STRINGSZ        = 200,
        MINLC           = 1,
index f113e3ec1e2fd51931647209a8bc5e27175e0fa3..6b43d2df436360ed0d059f7dd90164cc032a537b 100644 (file)
@@ -287,7 +287,7 @@ zsym(char *pn, Biobuf *f, Sym *h[])
 {      
        int o;
        
-       o = Bgetc(f);
+       o = BGETC(f);
        if(o < 0 || o >= NSYM || h[o] == nil)
                mangle(pn);
        return h[o];
@@ -301,12 +301,12 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
        Sym *s;
        Auto *u;
 
-       t = Bgetc(f);
+       t = BGETC(f);
        a->index = D_NONE;
        a->scale = 0;
        if(t & T_INDEX) {
-               a->index = Bgetc(f);
-               a->scale = Bgetc(f);
+               a->index = BGETC(f);
+               a->scale = BGETC(f);
        }
        a->offset = 0;
        if(t & T_OFFSET) {
@@ -330,7 +330,7 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
                a->type = D_SCONST;
        }
        if(t & T_TYPE)
-               a->type = Bgetc(f);
+               a->type = BGETC(f);
        if(a->type < 0 || a->type >= D_SIZE)
                mangle(pn);
        adrgotype = S;
@@ -405,10 +405,10 @@ newloop:
 loop:
        if(f->state == Bracteof || Boffset(f) >= eof)
                goto eof;
-       o = Bgetc(f);
+       o = BGETC(f);
        if(o == Beof)
                goto eof;
-       o |= Bgetc(f) << 8;
+       o |= BGETC(f) << 8;
        if(o <= AXXX || o >= ALAST) {
                if(o < 0)
                        goto eof;
@@ -421,8 +421,8 @@ loop:
                sig = 0;
                if(o == ASIGNAME)
                        sig = Bget4(f);
-               v = Bgetc(f);   /* type */
-               o = Bgetc(f);   /* sym */
+               v = BGETC(f);   /* type */
+               o = BGETC(f);   /* sym */
                r = 0;
                if(v == D_STATIC)
                        r = version;
index e48ad529bf05830faeb29d75b7d8d4df4abc21fc..bc1dfe8bf621b06ce8cf7d00de6c4f8b32b6b6e5 100644 (file)
@@ -320,6 +320,24 @@ dumpdata(void)
        pc = estrdat;
 }
 
+int
+dsname(Sym *s, int off, char *t, int n)
+{
+       Prog *p;
+
+       p = gins(ADATA, N, N);
+       p->from.type = D_EXTERN;
+       p->from.index = D_NONE;
+       p->from.offset = off;
+       p->from.scale = n;
+       p->from.sym = s;
+       
+       p->to.type = D_SCONST;
+       p->to.index = D_NONE;
+       memmove(p->to.sval, t, n);
+       return off + n;
+}
+
 /*
  * make a refer to the data s, s+len
  * emitting DATA if needed.
@@ -327,74 +345,13 @@ dumpdata(void)
 void
 datastring(char *s, int len, Addr *a)
 {
-       int w;
-       Prog *p;
-       Addr ac, ao;
-       static int gen;
-       struct {
-               Strlit lit;
-               char buf[100];
-       } tmp;
-
-       // string
-       memset(&ao, 0, sizeof(ao));
-       ao.type = D_STATIC;
-       ao.index = D_NONE;
-       ao.etype = TINT32;
-       ao.offset = 0;          // fill in
-
-       // constant
-       memset(&ac, 0, sizeof(ac));
-       ac.type = D_CONST;
-       ac.index = D_NONE;
-       ac.offset = 0;          // fill in
-
-       // huge strings are made static to avoid long names.
-       if(len > 100) {
-               snprint(namebuf, sizeof(namebuf), ".string.%d", gen++);
-               ao.sym = lookup(namebuf);
-               ao.type = D_STATIC;
-       } else {
-               if(len > 0 && s[len-1] == '\0')
-                       len--;
-               tmp.lit.len = len;
-               memmove(tmp.lit.s, s, len);
-               tmp.lit.s[len] = '\0';
-               len++;
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
-               ao.sym = pkglookup(namebuf, stringpkg);
-               ao.type = D_EXTERN;
-       }
-       *a = ao;
-
-       // only generate data the first time.
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       for(w=0; w<len; w+=8) {
-               p = pc;
-               gins(ADATA, N, N);
-
-               // DATA s+w, [NSNAME], $"xxx"
-               p->from = ao;
-               p->from.offset = w;
-
-               p->from.scale = NSNAME;
-               if(w+8 > len)
-                       p->from.scale = len-w;
-
-               p->to = ac;
-               p->to.type = D_SCONST;
-               p->to.offset = len;
-               memmove(p->to.sval, s+w, p->from.scale);
-       }
-       p = pc;
-       ggloblsym(ao.sym, len, ao.type == D_EXTERN);
-       if(ao.type == D_STATIC)
-               p->from.type = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(s, len);
+       a->type = D_EXTERN;
+       a->sym = sym;
+       a->offset = widthptr+4;  // skip header
+       a->etype = TINT32;
 }
 
 /*
@@ -404,76 +361,13 @@ datastring(char *s, int len, Addr *a)
 void
 datagostring(Strlit *sval, Addr *a)
 {
-       Prog *p;
-       Addr ac, ao, ap;
-       int32 wi, wp;
-       static int gen;
-
-       memset(&ac, 0, sizeof(ac));
-       memset(&ao, 0, sizeof(ao));
-       memset(&ap, 0, sizeof(ap));
-
-       // constant
-       ac.type = D_CONST;
-       ac.index = D_NONE;
-       ac.offset = 0;                  // fill in
-
-       // string len+ptr
-       ao.type = D_STATIC;             // fill in
-       ao.index = D_NONE;
-       ao.etype = TINT32;
-       ao.sym = nil;                   // fill in
-
-       // $string len+ptr
-       datastring(sval->s, sval->len, &ap);
-       ap.index = ap.type;
-       ap.type = D_ADDR;
-       ap.etype = TINT32;
-
-       wi = types[TUINT32]->width;
-       wp = types[tptr]->width;
-
-       if(ap.index == D_STATIC) {
-               // huge strings are made static to avoid long names
-               snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
-               ao.sym = lookup(namebuf);
-               ao.type = D_STATIC;
-       } else {
-               // small strings get named by their contents,
-               // so that multiple modules using the same string
-               // can share it.
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval);
-               ao.sym = pkglookup(namebuf, gostringpkg);
-               ao.type = D_EXTERN;
-       }
-
-       *a = ao;
-       if(ao.sym->flags & SymUniq)
-               return;
-       ao.sym->flags |= SymUniq;
-
-       data();
-       // DATA gostring, wp, $cstring
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->from.scale = wp;
-       p->to = ap;
-
-       // DATA gostring+wp, wi, $len
-       p = pc;
-       gins(ADATA, N, N);
-       p->from = ao;
-       p->from.offset = wp;
-       p->from.scale = wi;
-       p->to = ac;
-       p->to.offset = sval->len;
-
-       p = pc;
-       ggloblsym(ao.sym, types[TSTRING]->width, ao.type == D_EXTERN);
-       if(ao.type == D_STATIC)
-               p->from.type = D_STATIC;
-       text();
+       Sym *sym;
+       
+       sym = stringsym(sval->s, sval->len);
+       a->type = D_EXTERN;
+       a->sym = sym;
+       a->offset = 0;  // header
+       a->etype = TINT32;
 }
 
 void
index 62f470257358d61544807fd9ed167f0c466f2afa..ac0f3953f0e8c6037bc3417f147f092ac5adcf11 100644 (file)
@@ -139,6 +139,7 @@ struct      Sym
        int32   plt;
        int32   got;
        Sym*    hash;   // in hash table
+       Sym*    allsym; // in all symbol list
        Sym*    next;   // in text or data list
        Sym*    sub;    // in sub list
        Sym*    outer;  // container of sub
@@ -169,7 +170,6 @@ struct      Optab
 
 enum
 {
-       NHASH           = 10007,
        MINSIZ          = 4,
        STRINGSZ        = 200,
        MINLC           = 1,
index 39c316f2e53c1cbee143a244a042b9031d83946e..bb258a193d804415140ac822e6b191fca54111ec 100644 (file)
@@ -1001,8 +1001,10 @@ int      duint32(Sym *s, int off, uint32 v);
 int    duint64(Sym *s, int off, uint64 v);
 int    duint8(Sym *s, int off, uint8 v);
 int    duintptr(Sym *s, int off, uint64 v);
+int    dsname(Sym *s, int off, char *dat, int ndat);
 void   dumpobj(void);
 void   ieeedtod(uint64 *ieee, double native);
+Sym*   stringsym(char*, int);
 
 /*
  *     print.c
@@ -1237,3 +1239,5 @@ void      patch(Prog*, Prog*);
 void   zfile(Biobuf *b, char *p, int n);
 void   zhist(Biobuf *b, int line, vlong offset);
 void   zname(Biobuf *b, Sym *s, int t);
+void   data(void);
+void   text(void);
index b1e778d843bca8b2f990d01e1de69eaf09d94c63..bfd96274edeefa5396719318b33c2edd935d58d7 100644 (file)
@@ -124,9 +124,6 @@ main(int argc, char *argv[])
        runtimepkg = mkpkg(strlit("runtime"));
        runtimepkg->name = "runtime";
 
-       stringpkg = mkpkg(strlit("string"));
-       stringpkg->name = "string";
-
        typepkg = mkpkg(strlit("type"));
        typepkg->name = "type";
 
index fbabe0d43a5d70aba5464605a0c991b5a993bd43..9f4b7b318d08d75bb92aa7e30bb10768dcece204 100644 (file)
@@ -235,3 +235,57 @@ duintptr(Sym *s, int off, uint64 v)
 {
        return duintxx(s, off, v, widthptr);
 }
+
+Sym*
+stringsym(char *s, int len)
+{
+       static int gen;
+       Sym *sym;
+       int off, n, m;
+       struct {
+               Strlit lit;
+               char buf[110];
+       } tmp;
+       Pkg *pkg;
+
+       if(len > 100) {
+               // huge strings are made static to avoid long names
+               snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
+               pkg = localpkg;
+       } else {
+               // small strings get named by their contents,
+               // so that multiple modules using the same string
+               // can share it.
+               tmp.lit.len = len;
+               memmove(tmp.lit.s, s, len);
+               tmp.lit.s[len] = '\0';
+               snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp);
+               pkg = gostringpkg;
+       }
+       sym = pkglookup(namebuf, pkg);
+       
+       // SymUniq flag indicates that data is generated already
+       if(sym->flags & SymUniq)
+               return sym;
+       sym->flags |= SymUniq;
+       
+       data();
+       off = 0;
+       
+       // string header
+       off = dsymptr(sym, off, sym, widthptr+4);
+       off = duint32(sym, off, len);
+       
+       // string data
+       for(n=0; n<len; n+=m) {
+               m = 8;
+               if(m > len-n)
+                       m = len-n;
+               off = dsname(sym, off, s+n, m);
+       }
+       off = duint8(sym, off, 0);  // terminating NUL for runtime
+       ggloblsym(sym, off, 1);
+       text();
+       
+       return sym;     
+}
index 6b86462c44120d2fa3f3dc0e21c21072bc161779..b98e820c6da9c3c65752e97d1a3a72280e6c7b38 100644 (file)
@@ -348,17 +348,19 @@ dimportpath(Pkg *p)
  * uncommonType
  * ../../pkg/runtime/type.go:/uncommonType
  */
-static Sym*
-dextratype(Type *t)
+static int
+dextratype(Sym *sym, int off, Type *t, int ptroff)
 {
        int ot, n;
-       char *p;
        Sym *s;
        Sig *a, *m;
 
        m = methods(t);
        if(t->sym == nil && m == nil)
-               return nil;
+               return off;
+       
+       // fill in *extraType pointer in header
+       dsymptr(sym, ptroff, sym, off);
 
        n = 0;
        for(a=m; a; a=a->link) {
@@ -366,9 +368,8 @@ dextratype(Type *t)
                n++;
        }
 
-       p = smprint("_.%#T", t);
-       s = pkglookup(p, typepkg);
-       ot = 0;
+       ot = off;
+       s = sym;
        if(t->sym) {
                ot = dgostringptr(s, ot, t->sym->name);
                if(t != types[t->etype])
@@ -402,9 +403,8 @@ dextratype(Type *t)
                else
                        ot = duintptr(s, ot, 0);
        }
-       ggloblsym(s, ot, 0);
 
-       return s;
+       return ot;
 }
 
 enum {
@@ -570,7 +570,6 @@ static int
 dcommontype(Sym *s, int ot, Type *t)
 {
        int i;
-       Sym *s1;
        Sym *sptr;
        char *p;
 
@@ -582,8 +581,6 @@ dcommontype(Sym *s, int ot, Type *t)
        else
                sptr = weaktypesym(ptrto(t));
 
-       s1 = dextratype(t);
-
        // empty interface pointing at this type.
        // all the references that we emit are *interface{};
        // they point here.
@@ -620,11 +617,14 @@ dcommontype(Sym *s, int ot, Type *t)
        longsymnames = 0;
        ot = dgostringptr(s, ot, p);    // string
        free(p);
-       if(s1)
-               ot = dsymptr(s, ot, s1, 0);     // extraType
-       else
-               ot = duintptr(s, ot, 0);
-       ot = dsymptr(s, ot, sptr, 0);  // ptr to type
+       
+       // skip pointer to extraType,
+       // which follows the rest of this type structure.
+       // caller will fill in if needed.
+       // otherwise linker will assume 0.
+       ot += widthptr;
+
+       ot = dsymptr(s, ot, sptr, 0);  // ptrto type
        return ot;
 }
 
@@ -691,7 +691,7 @@ weaktypesym(Type *t)
 static Sym*
 dtypesym(Type *t)
 {
-       int ot, n, isddd, dupok;
+       int ot, xt, n, isddd, dupok;
        Sym *s, *s1, *s2;
        Sig *a, *m;
        Type *t1, *tbase;
@@ -723,15 +723,18 @@ dtypesym(Type *t)
 
 ok:
        ot = 0;
+       xt = 0;
        switch(t->etype) {
        default:
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                break;
 
        case TARRAY:
                // ../../pkg/runtime/type.go:/ArrayType
                s1 = dtypesym(t->type);
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s1, 0);
                if(t->bound < 0)
                        ot = duintptr(s, ot, -1);
@@ -743,6 +746,7 @@ ok:
                // ../../pkg/runtime/type.go:/ChanType
                s1 = dtypesym(t->type);
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s1, 0);
                ot = duintptr(s, ot, t->chan);
                break;
@@ -759,6 +763,7 @@ ok:
                        dtypesym(t1->type);
 
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = duint8(s, ot, isddd);
 
                // two slice headers: in and out.
@@ -790,6 +795,7 @@ ok:
 
                // ../../pkg/runtime/type.go:/InterfaceType
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s, ot+widthptr+2*4);
                ot = duint32(s, ot, n);
                ot = duint32(s, ot, n);
@@ -806,6 +812,7 @@ ok:
                s1 = dtypesym(t->down);
                s2 = dtypesym(t->type);
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s1, 0);
                ot = dsymptr(s, ot, s2, 0);
                break;
@@ -820,6 +827,7 @@ ok:
                // ../../pkg/runtime/type.go:/PtrType
                s1 = dtypesym(t->type);
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s1, 0);
                break;
 
@@ -832,6 +840,7 @@ ok:
                        n++;
                }
                ot = dcommontype(s, ot, t);
+               xt = ot - 2*widthptr;
                ot = dsymptr(s, ot, s, ot+widthptr+2*4);
                ot = duint32(s, ot, n);
                ot = duint32(s, ot, n);
@@ -853,7 +862,7 @@ ok:
                }
                break;
        }
-
+       ot = dextratype(s, ot, t, xt);
        ggloblsym(s, ot, dupok);
        return s;
 }
index 5d7394463df86b4d8756f8a49c83ac65b68f6e84..32dba459640fe8261b9dbc7155c1edd8c3b1e489 100644 (file)
@@ -733,18 +733,16 @@ dodata(void)
        last = nil;
        datap = nil;
 
-       for(h=0; h<NHASH; h++) {
-               for(s=hash[h]; s!=S; s=s->hash){
-                       if(!s->reachable || s->special)
-                               continue;
-                       if(STEXT < s->type && s->type < SXREF) {
-                               if(last == nil)
-                                       datap = s;
-                               else
-                                       last->next = s;
-                               s->next = nil;
-                               last = s;
-                       }
+       for(s=allsym; s!=S; s=s->allsym) {
+               if(!s->reachable || s->special)
+                       continue;
+               if(STEXT < s->type && s->type < SXREF) {
+                       if(last == nil)
+                               datap = s;
+                       else
+                               last->next = s;
+                       s->next = nil;
+                       last = s;
                }
        }
 
index ace38cbc5347ea3e7514c3b6a7d16bc5cfb7c385..bfdb1e7989e56c6ced4f313c72c09eacb5acee36 100644 (file)
@@ -989,8 +989,8 @@ lookup_or_diag(char *n)
 {
        Sym *s;
 
-       s = lookup(n, 0);
-       if (s->size == 0) {
+       s = rlookup(n, 0);
+       if (s == nil || s->size == 0) {
                diag("dwarf: missing type: %s", n);
                errorexit();
        }
@@ -1462,10 +1462,6 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
 
        if (strncmp(s, "go.string.", 10) == 0)
                return;
-       if (strncmp(s, "string.", 7) == 0)
-               return;
-       if (strncmp(s, "type._.", 7) == 0)
-               return;
 
        if (strncmp(s, "type.", 5) == 0 && strcmp(s, "type.*") != 0) {
                defgotype(sym);
@@ -2325,7 +2321,7 @@ dwarfemitdebugsections(void)
 {
        vlong infoe;
        DWDie* die;
-
+return;
        // For diagnostic messages.
        newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes");
 
index d5b0b03111ae2c58a3f511f3987b602ec767ff7e..b0cce4985d06d4a37d4ea8a086ddb11f923f13d5 100644 (file)
@@ -336,7 +336,7 @@ void
 elfdynhash(void)
 {
        Sym *s, *sy;
-       int i, h, nbucket, b;
+       int i, nbucket, b;
        uchar *pc;
        uint32 hc, g;
        uint32 *chain, *buckets;
@@ -367,26 +367,24 @@ elfdynhash(void)
        }
        memset(chain, 0, nsym * sizeof(uint32));
        memset(buckets, 0, nbucket * sizeof(uint32));
-       for(h = 0; h<NHASH; h++) {
-               for(sy=hash[h]; sy!=S; sy=sy->hash) {
-                       if (sy->dynid <= 0)
-                               continue;
-
-                       hc = 0;
-                       name = sy->dynimpname;
-                       if(name == nil)
-                               name = sy->name;
-                       for(pc = (uchar*)name; *pc; pc++) {
-                               hc = (hc<<4) + *pc;
-                               g = hc & 0xf0000000;
-                               hc ^= g >> 24;
-                               hc &= ~g;
-                       }
-
-                       b = hc % nbucket;
-                       chain[sy->dynid] = buckets[b];
-                       buckets[b] = sy->dynid;
+       for(sy=allsym; sy!=S; sy=sy->allsym) {
+               if (sy->dynid <= 0)
+                       continue;
+
+               hc = 0;
+               name = sy->dynimpname;
+               if(name == nil)
+                       name = sy->name;
+               for(pc = (uchar*)name; *pc; pc++) {
+                       hc = (hc<<4) + *pc;
+                       g = hc & 0xf0000000;
+                       hc ^= g >> 24;
+                       hc &= ~g;
                }
+
+               b = hc % nbucket;
+               chain[sy->dynid] = buckets[b];
+               buckets[b] = sy->dynid;
        }
 
        adduint32(s, nbucket);
index b76e469aed720365b6926534a5471535c8f98bb4..055163d08931ef5f9af64d43f073a85386fbe295 100644 (file)
@@ -658,8 +658,7 @@ deadcode(void)
        else
                last->next = nil;
        
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->hash)
+       for(s = allsym; s != S; s = s->allsym)
                if(strncmp(s->name, "weak.", 5) == 0) {
                        s->special = 1;  // do not lay out in data segment
                        s->reachable = 1;
@@ -670,16 +669,14 @@ deadcode(void)
 void
 doweak(void)
 {
-       int i;
        Sym *s, *t;
 
        // resolve weak references only if
        // target symbol will be in binary anyway.
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->hash) {
+       for(s = allsym; s != S; s = s->allsym) {
                if(strncmp(s->name, "weak.", 5) == 0) {
-                       t = lookup(s->name+5, s->version);
-                       if(t->type != 0 && t->reachable) {
+                       t = rlookup(s->name+5, s->version);
+                       if(t && t->type != 0 && t->reachable) {
                                s->value = t->value;
                                s->type = t->type;
                        } else {
index e645502b33840f30f42759fb3e41cbb249902753..75776bbc24156fd15946b49720dfc2958c791688 100644 (file)
@@ -470,8 +470,8 @@ eof:
        diag("truncated object file: %s", pn);
 }
 
-Sym*
-lookup(char *symb, int v)
+static Sym*
+_lookup(char *symb, int v, int creat)
 {
        Sym *s;
        char *p;
@@ -485,10 +485,12 @@ lookup(char *symb, int v)
        // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
        h &= 0xffffff;
        h %= NHASH;
+       c = symb[0];
        for(s = hash[h]; s != S; s = s->hash)
-               if(s->version == v)
                if(memcmp(s->name, symb, l) == 0)
                        return s;
+       if(!creat)
+               return nil;
 
        s = mal(sizeof(*s));
        if(debug['v'] > 1)
@@ -508,9 +510,25 @@ lookup(char *symb, int v)
        s->size = 0;
        hash[h] = s;
        nsymbol++;
+       
+       s->allsym = allsym;
+       allsym = s;
        return s;
 }
 
+Sym*
+lookup(char *name, int v)
+{
+       return _lookup(name, v, 1);
+}
+
+// read-only lookup
+Sym*
+rlookup(char *name, int v)
+{
+       return _lookup(name, v, 0);
+}
+
 void
 copyhistfrog(char *buf, int nbuf)
 {
@@ -1283,11 +1301,9 @@ headtype(char *name)
 void
 undef(void)
 {
-       int i;
        Sym *s;
 
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->hash)
+       for(s = allsym; s != S; s = s->allsym)
                if(s->type == SXREF)
                        diag("%s(%d): not defined", s->name, s->version);
 }
index fbd372b23dd7cee6fbb34f59299234cd90efb8bd..df90923612c344849a59b9802877610d685beee9 100644 (file)
@@ -56,6 +56,8 @@ enum
        SDYNIMPORT,
 
        SSUB = 1<<8,    /* sub-symbol, linked from parent via ->sub list */
+       
+       NHASH = 100003,
 };
 
 typedef struct Library Library;
@@ -106,6 +108,7 @@ EXTERN      Library*        library;
 EXTERN int     libraryp;
 EXTERN int     nlibrary;
 EXTERN Sym*    hash[NHASH];
+EXTERN Sym*    allsym;
 EXTERN Sym*    histfrog[MAXHIST];
 EXTERN uchar   fnuxi8[8];
 EXTERN uchar   fnuxi4[4];
@@ -133,6 +136,7 @@ void        asmlc(void);
 void   histtoauto(void);
 void   collapsefrog(Sym *s);
 Sym*   lookup(char *symb, int v);
+Sym*   rlookup(char *symb, int v);
 void   nuxiinit(void);
 int    find1(int32 l, int c);
 int    find2(int32 l, int c);
index e72b0b2a0d4086a5725b7dc1a3c8f9d359122f98..0d4240e36dcdcac4641120b66a2c47dd6a52206f 100644 (file)
@@ -171,12 +171,10 @@ initdynimport(void)
        Imp *m;
        Dll *d;
        Sym *s, *dynamic;
-       int i;
 
        dr = nil;
        
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->hash) {
+       for(s = allsym; s != S; s = s->allsym) {
                if(!s->reachable || !s->dynimpname || s->dynexport)
                        continue;
                for(d = dr; d != nil; d = d->next) {
@@ -312,12 +310,10 @@ scmp(const void *p1, const void *p2)
 static void
 initdynexport(void)
 {
-       int i;
        Sym *s;
        
        nexport = 0;
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->hash) {
+       for(s = allsym; s != S; s = s->allsym) {
                if(!s->reachable || !s->dynimpname || !s->dynexport)
                        continue;
                if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
index f1d44058e001b13a1b1937850d55c49e2d48d19f..aefe0b1af06bd363a6089ab9e984f6dbd0eb835f 100644 (file)
@@ -340,7 +340,6 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
 void
 symtab(void)
 {
-       int32 h;
        Sym *s;
 
        // Define these so that they'll get put into the symbol table.
@@ -361,11 +360,6 @@ symtab(void)
        s->size = 0;
        s->reachable = 1;
 
-       s = lookup("string.*", 0);
-       s->type = SSTRING;
-       s->size = 0;
-       s->reachable = 1;
-
        s = lookup("go.string.*", 0);
        s->type = SGOSTRING;
        s->size = 0;
@@ -380,22 +374,16 @@ symtab(void)
        // within a type they sort by size, so the .* symbols
        // just defined above will be first.
        // hide the specific symbols.
-       for(h=0; h<NHASH; h++) {
-               for(s=hash[h]; s!=S; s=s->hash){
-                       if(!s->reachable || s->special || s->type != SRODATA)
-                               continue;
-                       if(strncmp(s->name, "type.", 5) == 0) {
-                               s->type = STYPE;
-                               s->hide = 1;
-                       }
-                       if(strncmp(s->name, "string.", 7) == 0) {
-                               s->type = SSTRING;
-                               s->hide = 1;
-                       }
-                       if(strncmp(s->name, "go.string.", 10) == 0) {
-                               s->type = SGOSTRING;
-                               s->hide = 1;
-                       }
+       for(s = allsym; s != S; s = s->allsym) {
+               if(!s->reachable || s->special || s->type != SRODATA)
+                       continue;
+               if(strncmp(s->name, "type.", 5) == 0) {
+                       s->type = STYPE;
+                       s->hide = 1;
+               }
+               if(strncmp(s->name, "go.string.", 10) == 0) {
+                       s->type = SGOSTRING;
+                       s->hide = 1;
                }
        }