}
static Addr at, ao, ac, ad;
-static int wi, ot;
+static int wi, ws, ot;
void
ginsatoa(int fscale, int toffset)
* 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)
{
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;
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;
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);
}
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)
{
memset(&ad, 0, sizeof(ad));
wi = types[TINT32]->width;
+ ws = types[TINT16]->width;
// sig structure
at.type = D_EXTERN;
if(methodt->method && methodt->sym && !methodt->local)
continue;
+//print("s=%S\n", s);
dumpsigt(progt, ifacet, rcvrt, methodt, s);
}
*/
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
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("[");
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("}");
}
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("[");
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("}");
}
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.
}
}
- 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);
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;
}
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=");
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);
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);
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=");
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);
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
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,
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 {
} 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);
// 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*
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.
}
}
- 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;
}
// 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);