]> Cypherpunks repositories - gostls13.git/commitdiff
change format of Sigt and Sigi
authorKen Thompson <ken@golang.org>
Mon, 16 Mar 2009 22:27:08 +0000 (15:27 -0700)
committerKen Thompson <ken@golang.org>
Mon, 16 Mar 2009 22:27:08 +0000 (15:27 -0700)
to allow room for type hash
needed for log-time type switch.

R=r
OCL=26354
CL=26354

src/cmd/6g/obj.c
src/cmd/gc/subr.c
src/runtime/iface.c

index 02f987de0f6b68f6f751e377ba0faa3e2f3c804b..50d7244a424d51a6eed11c330ea4fd6a9b527b49 100644 (file)
@@ -470,7 +470,7 @@ sigcmp(Sig *a, Sig *b)
 }
 
 static Addr    at, ao, ac, ad;
-static int     wi, ot;
+static int     wi, ws, ot;
 
 void
 ginsatoa(int fscale, int toffset)
@@ -622,7 +622,26 @@ out:
  *     rcvrt - type used as method interface.  eqtype(ifacet, rcvrt) is always true,
  *             but ifacet might have a name that rcvrt does not.
  *     methodt - type with methods hanging off it (progt==*methodt sometimes)
+ *
+ * memory layout is Sigt struct from iface.c:
+ *     struct  Sigt
+ *     {
+ *             byte*   name;                   // name of basic type
+ *             Sigt*   link;                   // for linking into hash tables
+ *             uint32  thash;                  // hash of type
+ *             uint32  mhash;                  // hash of methods
+ *             uint16  width;                  // width of base type in bytes
+ *             uint16  alg;                    // algorithm
+ *             uint32  pad;
+ *             struct {
+ *                     byte*   fname;
+ *                     uint32  fhash;          // hash of type
+ *                     uint32  offset;         // offset of substruct
+ *                     void    (*fun)(void);
+ *             } meth[1];                      // one or more - last name is nil
+ *     };
  */
+
 void
 dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
 {
@@ -642,7 +661,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
        a = nil;
        o = 0;
        oldlist = nil;
-       sighash = 0;
+       sighash = typehash(progt, 0);
        for(f=methodt->method; f!=T; f=f->down) {
                if(f->type->etype != TFUNC)
                        continue;
@@ -688,8 +707,8 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
                                newname = a->sym;
                                oldname = methodsym(method, oldthis);
                                genptrtramp(method, oldname, oldthis, f->type, newname, newthis);
-                       }
-                       else if(f->embedded) {
+                       } else
+                       if(f->embedded) {
                                // TODO(rsc): only works for pointer receivers
                                if(oldlist == nil)
                                        oldlist = pc;
@@ -713,38 +732,23 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
        ot = 0;
        ot = rnd(ot, maxround); // base structure
 
-       // sigt[0].name = ""
-       ginsatoa(widthptr, stringo);
+       // base of type signature contains parameters
+       ginsatoa(widthptr, stringo);            // name
+       ot = rnd(ot, widthptr)+widthptr;        // skip link
+       gensatac(wi, typehash(progt, 0));       // thash
+       gensatac(wi, sighash);                  // mhash
+       gensatac(ws, progt->width);             // width
+       gensatac(ws, algtype(progt));           // algorithm
 
-       // save type name for runtime error message.
        snprint(buf, sizeof buf, "%#T", progt);
        datastring(buf, strlen(buf)+1);
 
-       // first field of an type signature contains
-       // the element parameters and is not a real entry
-       // sigt[0].hash = elemalg + sighash<<8
-       gensatac(wi, algtype(progt) + (sighash<<8));
-
-       // sigt[0].offset = width
-       gensatac(wi, progt->width);
-
-       // skip the function
-       gensatac(widthptr, 0);
-
        for(b=a; b!=nil; b=b->link) {
-               ot = rnd(ot, maxround); // base structure
-
-               // sigt[++].name = "fieldname"
-               ginsatoa(widthptr, stringo);
-
-               // sigt[++].hash = hashcode
-               gensatac(wi, b->hash);
-
-               // sigt[++].offset = of embedded struct
-               gensatac(wi, 0);
-
-               // sigt[++].fun = &method
-               gensatad(b->sym);
+               ot = rnd(ot, maxround);         // base of substructure
+               ginsatoa(widthptr, stringo);    // field name
+               gensatac(wi, b->hash);          // hash
+               gensatac(wi, 0);                // offset
+               gensatad(b->sym);               // &method
 
                datastring(b->name, strlen(b->name)+1);
        }
@@ -765,6 +769,20 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
        p->to.offset = ot;
 }
 
+/*
+ * memory layout is Sigi struct from iface.c:
+ *     struct  Sigi
+ *     {
+ *             byte*   name;
+ *             uint32  hash;
+ *             uint32  size;                   // number of methods
+ *             struct {
+ *                     byte*   fname;
+ *                     uint32  fhash;
+ *                     uint32  perm;           // location of fun in Sigt
+ *             } meth[1];                      // [size+1] - last name is nil
+ *     };
+ */
 void
 dumpsigi(Type *t, Sym *s)
 {
@@ -875,6 +893,7 @@ dumpsignatures(void)
        memset(&ad, 0, sizeof(ad));
 
        wi = types[TINT32]->width;
+       ws = types[TINT16]->width;
 
        // sig structure
        at.type = D_EXTERN;
@@ -986,6 +1005,7 @@ dumpsignatures(void)
                if(methodt->method && methodt->sym && !methodt->local)
                        continue;
 
+//print("s=%S\n", s);
                dumpsigt(progt, ifacet, rcvrt, methodt, s);
        }
 
index 80405e37cd8e162f3a72d69e85ea7642693e6615..a112849a8e3bb71c9d2a79f39ff5b847c463f4c9 100644 (file)
@@ -1929,10 +1929,6 @@ typehash(Type *at, int d)
        if(d >= 5)
                return PRIME3;
 
-       if(at->recur)
-               return 0;
-       at->recur = 1;
-
        h = at->etype*PRIME4;
 
        switch(at->etype) {
@@ -1961,7 +1957,6 @@ typehash(Type *at, int d)
                break;
        }
 
-       at->recur = 0;
        return h;
 }
 
index 34c4a2da8b60b4071262e28a68553c483c123d41..5526ca7ecf4bd598b76436eb9e3406895adc9d52 100644 (file)
@@ -15,17 +15,31 @@ typedef     struct  Itype   Itype;
  */
 struct Sigt
 {
-       byte*   name;
-       uint32  hash;           // hash of type         // first is alg
-       uint32  offset;         // offset of substruct  // first is width
-       void    (*fun)(void);
+       byte*   name;                   // name of basic type
+       Sigt*   link;                   // for linking into hash tables
+       uint32  thash;                  // hash of type
+       uint32  mhash;                  // hash of methods
+       uint16  width;                  // width of base type in bytes
+       uint16  alg;                    // algorithm
+       uint32  pad;
+       struct {
+               byte*   fname;
+               uint32  fhash;          // hash of type
+               uint32  offset;         // offset of substruct
+               void    (*fun)(void);
+       } meth[1];                      // one or more - last name is nil
 };
 
 struct Sigi
 {
        byte*   name;
        uint32  hash;
-       uint32  perm;           // location of fun in Sigt // first is size
+       uint32  size;                   // number of methods
+       struct {
+               byte*   fname;
+               uint32  fhash;
+               uint32  perm;           // location of fun in Sigt
+       } meth[1];                      // [size+1] - last name is nil
 };
 
 struct Itype
@@ -52,10 +66,10 @@ printsigi(Sigi *si)
 
        sys·printpointer(si);
        prints("{");
-       prints((int8*)si[0].name);
+       prints((int8*)si->name);
        prints(":");
-       for(i=1;; i++) {
-               name = si[i].name;
+       for(i=0;; i++) {
+               name = si->meth[i].fname;
                if(name == nil)
                        break;
                prints("[");
@@ -63,9 +77,9 @@ printsigi(Sigi *si)
                prints("]\"");
                prints((int8*)name);
                prints("\"");
-               sys·printint(si[i].hash%999);
+               sys·printint(si->meth[i].fhash%999);
                prints("/");
-               sys·printint(si[i].perm);
+               sys·printint(si->meth[i].perm);
        }
        prints("}");
 }
@@ -78,13 +92,17 @@ printsigt(Sigt *st)
 
        sys·printpointer(st);
        prints("{");
-       prints((int8*)st[0].name);
+       prints((int8*)st->name);
        prints(":");
-       sys·printint(st[0].hash);      // first element has alg
+       sys·printint(st->thash%999);   // type hash
+       prints(",");
+       sys·printint(st->mhash%999);   // method hash
+       prints(",");
+       sys·printint(st->width);       // width
        prints(",");
-       sys·printint(st[0].offset);    // first element has width
-       for(i=1;; i++) {
-               name = st[i].name;
+       sys·printint(st->alg); // algorithm
+       for(i=0;; i++) {
+               name = st->meth[i].fname;
                if(name == nil)
                        break;
                prints("[");
@@ -92,11 +110,11 @@ printsigt(Sigt *st)
                prints("]\"");
                prints((int8*)name);
                prints("\"");
-               sys·printint(st[i].hash%999);
+               sys·printint(st->meth[i].fhash%999);
                prints("/");
-               sys·printint(st[i].offset);
+               sys·printint(st->meth[i].offset);
                prints("/");
-               sys·printpointer(st[i].fun);
+               sys·printpointer(st->meth[i].fun);
        }
        prints("}");
 }
@@ -124,8 +142,11 @@ itype(Sigi *si, Sigt *st, int32 canfail)
        h = 0;
        if(si)
                h += si->hash;
-       if(st)
-               h += st->hash >> 8;
+       if(st) {
+               h += st->thash;
+               h += st->mhash;
+       }
+
        h %= nelem(hash);
 
        // look twice - once without lock, once with.
@@ -156,30 +177,30 @@ itype(Sigi *si, Sigt *st, int32 canfail)
                }
        }
 
-       ni = si[0].perm;        // first entry has size
+       ni = si->size;
        m = mal(sizeof(*m) + ni*sizeof(m->fun[0]));
        m->sigi = si;
        m->sigt = st;
 
 throw:
-       nt = 1;
-       for(ni=1;; ni++) {      // ni=1: skip first word
-               iname = si[ni].name;
+       nt = 0;
+       for(ni=0;; ni++) {
+               iname = si->meth[ni].fname;
                if(iname == nil)
                        break;
 
                // pick up next name from
                // interface signature
-               ihash = si[ni].hash;
+               ihash = si->meth[ni].fhash;
 
                for(;; nt++) {
                        // pick up and compare next name
                        // from structure signature
-                       sname = st[nt].name;
+                       sname = st->meth[nt].fname;
                        if(sname == nil) {
                                if(!canfail) {
                                        printf("cannot convert type %s to interface %s: missing method %s\n",
-                                               st[0].name, si[0].name, iname);
+                                               st->name, si->name, iname);
                                        if(iface_debug) {
                                                prints("interface");
                                                printsigi(si);
@@ -196,16 +217,17 @@ throw:
                                        unlock(&ifacelock);
                                return nil;
                        }
-                       if(ihash == st[nt].hash && strcmp(sname, iname) == 0)
+                       if(ihash == st->meth[nt].fhash && strcmp(sname, iname) == 0)
                                break;
                }
-               m->fun[si[ni].perm] = st[nt].fun;
+               m->fun[si->meth[ni].perm] = st->meth[nt].fun;
        }
        m->link = hash[h];
        hash[h] = m;
-       // printf("new itype %p\n", m);
        if(locked)
                unlock(&ifacelock);
+
+       // printf("new itype %p\n", m);
        return m;
 }
 
@@ -218,9 +240,6 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...)
        int32 alg, wid;
 
        elem = (byte*)(&st+1);
-       wid = st->offset;
-       ret = (Iface*)(elem + rnd(wid, 8));
-       ret->type = itype(si, st, 0);
 
        if(iface_debug) {
                prints("T2I sigi=");
@@ -232,11 +251,14 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...)
                prints("\n");
        }
 
-       alg = st->hash & 0xFF;
-       wid = st->offset;
-       if(wid <= sizeof ret->data)
+       wid = st->width;
+       alg = st->alg;
+       ret = (Iface*)(elem + rnd(wid, 8));
+       ret->type = itype(si, st, 0);
+
+       if(wid <= sizeof(ret->data))
                algarray[alg].copy(wid, &ret->data, elem);
-       else{
+       else {
                ret->data = mal(wid);
                if(iface_debug)
                        printf("T2I mal %d %p\n", wid, ret->data);
@@ -273,24 +295,24 @@ sys·ifaceI2T(Sigt *st, Iface i, ...)
        im = i.type;
        if(im == nil) {
                prints("interface is nil, not ");
-               prints((int8*)st[0].name);
+               prints((int8*)st->name);
                prints("\n");
                throw("interface conversion");
        }
 
        if(im->sigt != st) {
-               prints((int8*)im->sigi[0].name);
+               prints((int8*)im->sigi->name);
                prints(" is ");
-               prints((int8*)im->sigt[0].name);
+               prints((int8*)im->sigt->name);
                prints(", not ");
-               prints((int8*)st[0].name);
+               prints((int8*)st->name);
                prints("\n");
                throw("interface conversion");
        }
 
-       alg = st->hash & 0xFF;
-       wid = st->offset;
-       if(wid <= sizeof i.data)
+       alg = st->alg;
+       wid = st->width;
+       if(wid <= sizeof(i.data))
                algarray[alg].copy(wid, ret, &i.data);
        else
                algarray[alg].copy(wid, ret, i.data);
@@ -312,10 +334,6 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...)
        Itype *im;
        int32 alg, wid;
 
-       ret = (byte*)(&i+1);
-       alg = st->hash & 0xFF;
-       wid = st->offset;
-       ok = (bool*)(ret+rnd(wid, 1));
 
        if(iface_debug) {
                prints("I2T2 sigt=");
@@ -325,13 +343,18 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...)
                prints("\n");
        }
 
+       ret = (byte*)(&i+1);
+       alg = st->alg;
+       wid = st->width;
+       ok = (bool*)(ret+rnd(wid, 1));
+
        im = i.type;
        if(im == nil || im->sigt != st) {
                *ok = false;
                sys·memclr(ret, wid);
        } else {
                *ok = true;
-               if(wid <= sizeof i.data)
+               if(wid <= sizeof(i.data))
                        algarray[alg].copy(wid, ret, &i.data);
                else
                        algarray[alg].copy(wid, ret, i.data);
@@ -424,21 +447,23 @@ uint64
 ifacehash(Iface a)
 {
        int32 alg, wid;
+       Sigt *sigt;
 
        if(a.type == nil)
                return 0;
-       alg = a.type->sigt->hash & 0xFF;
-       wid = a.type->sigt->offset;
+
+       sigt = a.type->sigt;
+       alg = sigt->alg;
+       wid = sigt->width;
        if(algarray[alg].hash == nohash) {
                // calling nohash will throw too,
                // but we can print a better error.
-               printf("hash of unhashable type %s\n", a.type->sigt->name);
+               printf("hash of unhashable type %s\n", sigt->name);
                throw("interface hash");
        }
-       if(wid <= sizeof a.data)
+       if(wid <= sizeof(a.data))
                return algarray[alg].hash(wid, &a.data);
-       else
-               return algarray[alg].hash(wid, a.data);
+       return algarray[alg].hash(wid, a.data);
 }
 
 bool
@@ -470,8 +495,8 @@ ifaceeq(Iface i1, Iface i2)
        if(i1.type->sigt != i2.type->sigt)
                goto no;
 
-       alg = i1.type->sigt->hash & 0xFF;
-       wid = i1.type->sigt->offset;
+       alg = i1.type->sigt->alg;
+       wid = i1.type->sigt->width;
 
        if(algarray[alg].equal == noequal) {
                // calling noequal will throw too,
@@ -480,7 +505,7 @@ ifaceeq(Iface i1, Iface i2)
                throw("interface compare");
        }
 
-       if(wid <= sizeof i1.data) {
+       if(wid <= sizeof(i1.data)) {
                if(!algarray[alg].equal(wid, &i1.data, &i2.data))
                        goto no;
        } else {
@@ -525,8 +550,8 @@ sys·Reflect(Iface i, uint64 retit, string rettype, bool retindir)
        } else {
                retit = (uint64)i.data;
                rettype = gostring(i.type->sigt->name);
-               wid = i.type->sigt->offset;
-               retindir = wid > sizeof i.data;
+               wid = i.type->sigt->width;
+               retindir = wid > sizeof(i.data);
        }
        FLUSH(&retit);
        FLUSH(&rettype);
@@ -568,7 +593,7 @@ extern int32 ngotypesigs;
 // signature with type string "[]int" in gotypesigs, and unreflect
 // wouldn't call fakesigt.
 
-static Sigt    *fake[1009];
+static Sigt*   fake[1009];
 static int32   nfake;
 
 static Sigt*
@@ -590,7 +615,7 @@ fakesigt(string type, bool indir)
        for(locked=0; locked<2; locked++) {
                if(locked)
                        lock(&ifacelock);
-               for(sigt = fake[h]; sigt != nil; sigt = (Sigt*)sigt->fun) {
+               for(sigt = fake[h]; sigt != nil; sigt = sigt->link) {
                        // don't need to compare indir.
                        // same type string but different indir will have
                        // different hashes.
@@ -603,16 +628,16 @@ fakesigt(string type, bool indir)
                }
        }
 
-       sigt = mal(2*sizeof sigt[0]);
-       sigt[0].name = mal(type->len + 1);
-       mcpy(sigt[0].name, type->str, type->len);
-       sigt[0].hash = AFAKE;   // alg
+       sigt = mal(sizeof(*sigt));
+       sigt->name = mal(type->len + 1);
+       mcpy(sigt->name, type->str, type->len);
+       sigt->alg = AFAKE;
+       sigt->width = 1;  // small width
        if(indir)
-               sigt[0].offset = 2*sizeof(niliface.data);  // big width
-       else
-               sigt[0].offset = 1;  // small width
-       sigt->fun = (void*)fake[h];
+               sigt->width = 2*sizeof(niliface.data);  // big width
+       sigt->link = fake[h];
        fake[h] = sigt;
+
        unlock(&ifacelock);
        return sigt;
 }
@@ -672,7 +697,7 @@ sys·Unreflect(uint64 it, string type, bool indir, Iface ret)
        // if we think the type should be indirect
        // and caller does not, play it safe, return nil.
        sigt = findtype(type, indir);
-       if(indir != (sigt[0].offset > sizeof ret.data))
+       if(indir != (sigt->width > sizeof(ret.data)))
                goto out;
 
        ret.type = itype(sigi·empty, sigt, 0);