]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use new reflect data structures (CL 31107)
authorRuss Cox <rsc@golang.org>
Tue, 7 Jul 2009 18:02:54 +0000 (11:02 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 7 Jul 2009 18:02:54 +0000 (11:02 -0700)
in place of sigi, sigt.

R=ken
OCL=31118
CL=31277

src/cmd/gc/sys.go
src/pkg/runtime/Makefile
src/pkg/runtime/iface.c
src/pkg/runtime/print.c
src/pkg/runtime/runtime.h

index a8a11866d8bb13b8f131277908630f005fc9f547..aad0a980492ebc9d05d7c4da1566fcd5a910e421 100644 (file)
@@ -36,17 +36,17 @@ func        stringiter(string, int) int;
 func   stringiter2(string, int) (retk int, retv int);
 
 func   ifaceI2E(iface any) (ret any);
-func   ifaceE2I(sigi *byte, iface any) (ret any);
-func   ifaceT2E(sigt *byte, elem any) (ret any);
-func   ifaceE2T(sigt *byte, elem any) (ret any);
-func   ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
-func   ifaceE2T2(sigt *byte, elem any) (ret any, ok bool);
-func   ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
-func   ifaceI2T(sigt *byte, iface any) (ret any);
-func   ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
-func   ifaceI2I(sigi *byte, iface any) (ret any);
-func   ifaceI2Ix(sigi *byte, iface any) (ret any);
-func   ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
+func   ifaceE2I(typ *byte, iface any) (ret any);
+func   ifaceT2E(typ *byte, elem any) (ret any);
+func   ifaceE2T(typ *byte, elem any) (ret any);
+func   ifaceE2I2(typ *byte, iface any) (ret any, ok bool);
+func   ifaceE2T2(typ *byte, elem any) (ret any, ok bool);
+func   ifaceT2I(typ1 *byte, typ2 *byte, elem any) (ret any);
+func   ifaceI2T(typ *byte, iface any) (ret any);
+func   ifaceI2T2(typ *byte, iface any) (ret any, ok bool);
+func   ifaceI2I(typ *byte, iface any) (ret any);
+func   ifaceI2Ix(typ *byte, iface any) (ret any);
+func   ifaceI2I2(typ *byte, iface any) (ret any, ok bool);
 func   ifaceeq(i1 any, i2 any) (ret bool);
 func   efaceeq(i1 any, i2 any) (ret bool);
 func   ifacethash(i1 any) (ret uint32);
index 4e932b0525e90dcb2bfe2874932cb5533c654960..f3eb4046a08557e2fd88b351cd7fea4aeea04214 100644 (file)
@@ -70,6 +70,7 @@ OFILES=\
        sys.$O\
        thread.$O\
        traceback.$O\
+       type.$O\
        $(OFILES_$(GOARCH))\
 
 HFILES=\
index 6c933b1b2a922e417e95bc43eab45aaf34adf6de..cc9eb7eede18690d08e0c8c5368749182ba35c19 100644 (file)
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "type.h"
 
-int32  iface_debug     = 0;
+static void
+printiface(Iface i)
+{
+       printf("(%p,%p)", i.tab, i.data);
+}
 
-typedef        struct  Sigt    Sigt;
-typedef        struct  Sigi    Sigi;
-typedef        struct  Itype   Itype;
+static void
+printeface(Eface e)
+{
+       printf("(%p,%p)", e.type, e.data);
+}
 
 /*
- * the layout of Iface, Sigt and Sigi are known to the compiler
+ * layout of Itab known to compilers
  */
-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
-       // note: on amd64 there is a 32-bit pad here.
-       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  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
+struct Itab
 {
-       Sigi*   sigi;
-       Sigt*   sigt;
-       Itype*  link;
+       InterfaceType*  inter;
+       Type*   type;
+       Itab*   link;
        int32   bad;
        int32   unused;
        void    (*fun[])(void);
 };
 
-static Iface   niliface;
-static Eface   nileface;
-
-static Itype*  hash[1009];
+static Itab*   hash[1009];
 static Lock    ifacelock;
 
-Sigi   sigi·empty[2] =        { (byte*)"interface { }" };
-
-static void
-printsigi(Sigi *si)
-{
-       int32 i;
-       byte *name;
-
-       sys·printpointer(si);
-       prints("{");
-       prints((int8*)si->name);
-       prints(":");
-       for(i=0;; i++) {
-               name = si->meth[i].fname;
-               if(name == nil)
-                       break;
-               prints("[");
-               sys·printint(i);
-               prints("]\"");
-               prints((int8*)name);
-               prints("\"");
-               sys·printint(si->meth[i].fhash%999);
-               prints("/");
-               sys·printint(si->meth[i].perm);
-       }
-       prints("}");
-}
-
-static void
-printsigt(Sigt *st)
-{
-       int32 i;
-       byte *name;
-
-       sys·printpointer(st);
-       prints("{");
-       prints((int8*)st->name);
-       prints(":");
-       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->alg); // algorithm
-       for(i=0;; i++) {
-               name = st->meth[i].fname;
-               if(name == nil)
-                       break;
-               prints("[");
-               sys·printint(i);
-               prints("]\"");
-               prints((int8*)name);
-               prints("\"");
-               sys·printint(st->meth[i].fhash%999);
-               prints("/");
-               sys·printint(st->meth[i].offset);
-               prints("/");
-               sys·printpointer(st->meth[i].fun);
-       }
-       prints("}");
-}
-
-static void
-printiface(Iface i)
-{
-       prints("(");
-       sys·printpointer(i.type);
-       prints(",");
-       sys·printpointer(i.data);
-       prints(")");
-}
-
-static void
-printeface(Eface e)
-{
-       prints("(");
-       sys·printpointer(e.type);
-       prints(",");
-       sys·printpointer(e.data);
-       prints(")");
-}
-
-static Itype*
-itype(Sigi *si, Sigt *st, int32 canfail)
+static Itab*
+itab(InterfaceType *inter, Type *type, int32 canfail)
 {
        int32 locked;
-       int32 nt, ni;
+       int32 ni;
+       Method *t, *et;
+       IMethod *i, *ei;
        uint32 ihash, h;
-       byte *sname, *iname;
-       Itype *m;
+       String *iname;
+       Itab *m;
+       UncommonType *x;
 
-       if(si->size == 0)
-               throw("internal error - misuse of itype");
+       if(inter->mhdr.nel == 0)
+               throw("internal error - misuse of itab");
 
        // easy case
-       if(st->meth[0].fname == nil) {
+       x = type->x;
+       if(x == nil) {
                if(canfail)
                        return nil;
-               iname = si->meth[0].fname;
-               goto throw1;
+               iname = inter->m[0].name;
+               goto throw;
        }
 
        // compiler has provided some good hash codes for us.
-       h = 0;
-       if(si)
-               h += si->hash;
-       if(st) {
-               h += st->thash;
-               h += st->mhash;
-       }
-
+       h = inter->hash;
+       h += 17 * type->hash;
+       // TODO(rsc): h += 23 * x->mhash ?
        h %= nelem(hash);
 
        // look twice - once without lock, once with.
@@ -178,7 +69,7 @@ itype(Sigi *si, Sigt *st, int32 canfail)
                if(locked)
                        lock(&ifacelock);
                for(m=hash[h]; m!=nil; m=m->link) {
-                       if(m->sigi == si && m->sigt == st) {
+                       if(m->inter == inter && m->type == type) {
                                if(m->bad) {
                                        m = nil;
                                        if(!canfail) {
@@ -188,8 +79,8 @@ itype(Sigi *si, Sigt *st, int32 canfail)
                                                // the cached result doesn't record which
                                                // interface function was missing, so jump
                                                // down to the interface check, which will
-                                               // give a better error.
-                                               goto throw;
+                                               // do more work but give a better error.
+                                               goto search;
                                        }
                                }
                                if(locked)
@@ -199,69 +90,60 @@ itype(Sigi *si, Sigt *st, int32 canfail)
                }
        }
 
-       ni = si->size;
-       m = malloc(sizeof(*m) + ni*sizeof(m->fun[0]));
-       m->sigi = si;
-       m->sigt = st;
-
-throw:
-       nt = 0;
-       for(ni=0;; ni++) {
-               iname = si->meth[ni].fname;
-               if(iname == nil)
-                       break;
-
-               // pick up next name from
-               // interface signature
-               ihash = si->meth[ni].fhash;
-
-               for(;; nt++) {
-                       // pick up and compare next name
-                       // from structure signature
-                       sname = st->meth[nt].fname;
-                       if(sname == nil) {
+       ni = inter->mhdr.nel;
+       m = malloc(sizeof(*m) + ni*sizeof m->fun[0]);
+       m->inter = inter;
+       m->type = type;
+
+search:
+       // both inter and type have method sorted by hash,
+       // so can iterate over both in lock step;
+       // the loop is O(ni+nt) not O(ni*nt).
+       i = inter->m;
+       ei = i + inter->mhdr.nel;
+       t = x->m;
+       et = t + x->mhdr.nel;
+       for(; i < ei; i++) {
+               ihash = i->hash;
+               iname = i->name;
+               for(;; t++) {
+                       if(t >= et) {
                                if(!canfail) {
-                               throw1:
-                                       printf("cannot convert type %s to interface %s: missing method %s\n",
-                                               st->name, si->name, iname);
-                                       if(iface_debug) {
-                                               prints("interface");
-                                               printsigi(si);
-                                               prints("\ntype");
-                                               printsigt(st);
-                                               prints("\n");
-                                       }
+                               throw:
+                                       // didn't find method
+                                       printf("%S is not %S: missing method %S\n",
+                                               *type->string, *inter->string, *iname);
                                        throw("interface conversion");
                                        return nil;     // not reached
                                }
                                m->bad = 1;
-                               m->link = hash[h];
-                               hash[h] = m;
-                               if(locked)
-                                       unlock(&ifacelock);
-                               return nil;
+                               goto out;
                        }
-                       if(ihash == st->meth[nt].fhash && strcmp(sname, iname) == 0)
+                       if(t->hash == ihash && t->name == iname)
                                break;
                }
-               m->fun[si->meth[ni].perm] = st->meth[nt].fun;
+               if(m)
+                       m->fun[i->perm] = t->ifn;
        }
+
+out:
        m->link = hash[h];
        hash[h] = m;
        if(locked)
                unlock(&ifacelock);
-
+       if(m->bad)
+               return nil;
        return m;
 }
 
 static void
-copyin(Sigt *st, void *src, void **dst)
+copyin(Type *t, void *src, void **dst)
 {
        int32 wid, alg;
        void *p;
 
-       wid = st->width;
-       alg = st->alg;
+       wid = t->size;
+       alg = t->alg;
 
        if(wid <= sizeof(*dst))
                algarray[alg].copy(wid, dst, src);
@@ -273,12 +155,12 @@ copyin(Sigt *st, void *src, void **dst)
 }
 
 static void
-copyout(Sigt *st, void **src, void *dst)
+copyout(Type *t, void **src, void *dst)
 {
        int32 wid, alg;
 
-       wid = st->width;
-       alg = st->alg;
+       wid = t->size;
+       alg = t->alg;
 
        if(wid <= sizeof(*src))
                algarray[alg].copy(wid, dst, src);
@@ -286,132 +168,123 @@ copyout(Sigt *st, void **src, void *dst)
                algarray[alg].copy(wid, dst, *src);
 }
 
-// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
+// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret Iface);
 #pragma textflag 7
 void
-sys·ifaceT2I(Sigi *si, Sigt *st, ...)
+sys·ifaceT2I(InterfaceType *inter, Type *t, ...)
 {
        byte *elem;
        Iface *ret;
        int32 wid;
 
-       elem = (byte*)(&st+1);
-       wid = st->width;
-       ret = (Iface*)(elem + rnd(wid, sizeof(uintptr)));
-
-       ret->type = itype(si, st, 0);
-       copyin(st, elem, &ret->data);
+       elem = (byte*)(&t+1);
+       wid = t->size;
+       ret = (Iface*)(elem + rnd(wid, Structrnd));
+       ret->tab = itab(inter, t, 0);
+       copyin(t, elem, &ret->data);
 }
 
-// ifaceT2E(sigt *byte, elem any) (ret any);
+// ifaceT2E(sigt *byte, elem any) (ret Eface);
 #pragma textflag 7
 void
-sys·ifaceT2E(Sigt *st, ...)
+sys·ifaceT2E(Type *t, ...)
 {
        byte *elem;
        Eface *ret;
        int32 wid;
 
-       elem = (byte*)(&st+1);
-       wid = st->width;
-       ret = (Eface*)(elem + rnd(wid, sizeof(uintptr)));
+       elem = (byte*)(&t+1);
+       wid = t->size;
+       ret = (Eface*)(elem + rnd(wid, Structrnd));
 
-       ret->type = st;
-       copyin(st, elem, &ret->data);
+       ret->type = t;
+       copyin(t, elem, &ret->data);
 }
 
 // ifaceI2T(sigt *byte, iface any) (ret any);
 #pragma textflag 7
 void
-sys·ifaceI2T(Sigt *st, Iface i, ...)
+sys·ifaceI2T(Type *t, Iface i, ...)
 {
-       Itype *im;
+       Itab *tab;
        byte *ret;
 
        ret = (byte*)(&i+1);
-
-       im = i.type;
-       if(im == nil) {
-               printf("interface is nil, not %s\n", st->name);
+       tab = i.tab;
+       if(tab == nil) {
+               printf("interface is nil, not %S\n", *t->string);
                throw("interface conversion");
        }
-       if(im->sigt != st) {
-               printf("%s is %s, not %s\n", im->sigi->name, im->sigt->name, st->name);
+       if(tab->type != t) {
+               printf("%S is %S, not %S\n", *tab->inter->string, *tab->type->string, *t->string);
                throw("interface conversion");
        }
-       copyout(st, &i.data, ret);
+       copyout(t, &i.data, ret);
 }
 
-// ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
+// ifaceI2T2(sigt *byte, i Iface) (ret any, ok bool);
 #pragma textflag 7
 void
-sys·ifaceI2T2(Sigt *st, Iface i, ...)
+sys·ifaceI2T2(Type *t, Iface i, ...)
 {
        byte *ret;
        bool *ok;
-       Itype *im;
        int32 wid;
 
        ret = (byte*)(&i+1);
-       wid = st->width;
+       wid = t->size;
        ok = (bool*)(ret+rnd(wid, 1));
 
-       im = i.type;
-       if(im == nil || im->sigt != st) {
+       if(i.tab == nil || i.tab->type != t) {
                *ok = false;
                sys·memclr(ret, wid);
                return;
        }
 
        *ok = true;
-       copyout(st, &i.data, ret);
+       copyout(t, &i.data, ret);
 }
 
-// ifaceE2T(sigt *byte, iface any) (ret any);
+// ifaceE2T(sigt *byte, e Eface) (ret any);
 #pragma textflag 7
 void
-sys·ifaceE2T(Sigt *st, Eface e, ...)
+sys·ifaceE2T(Type *t, Eface e, ...)
 {
-       Sigt *t;
        byte *ret;
 
        ret = (byte*)(&e+1);
 
-       t = e.type;
-       if(t == nil) {
-               printf("interface is nil, not %s\n", st->name);
-               throw("interface conversion");
-       }
-       if(t != st) {
-               printf("interface is %s, not %s\n", t->name, st->name);
+       if(e.type != t) {
+               if(e.type == nil)
+                       printf("interface is nil, not %S\n", *t->string);
+               else
+                       printf("interface is %S, not %S\n", *e.type->string, *t->string);
                throw("interface conversion");
        }
-       copyout(st, &e.data, ret);
+       copyout(t, &e.data, ret);
 }
 
 // ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
 #pragma textflag 7
 void
-sys·ifaceE2T2(Sigt *st, Eface e, ...)
+sys·ifaceE2T2(Type *t, Eface e, ...)
 {
        byte *ret;
        bool *ok;
-       Sigt *t;
        int32 wid;
 
        ret = (byte*)(&e+1);
-       wid = st->width;
+       wid = t->size;
        ok = (bool*)(ret+rnd(wid, 1));
 
-       t = e.type;
-       if(t != st) {
+       if(t != e.type) {
                *ok = false;
                sys·memclr(ret, wid);
                return;
        }
 
        *ok = true;
-       copyout(st, &e.data, ret);
+       copyout(t, &e.data, ret);
 }
 
 // ifaceI2E(sigi *byte, iface any) (ret any);
@@ -419,33 +292,35 @@ sys·ifaceE2T2(Sigt *st, Eface e, ...)
 void
 sys·ifaceI2E(Iface i, Eface ret)
 {
-       Itype *im;
+       Itab *tab;
 
        ret.data = i.data;
-       im = i.type;
-       if(im == nil)
+       tab = i.tab;
+       if(tab == nil)
                ret.type = nil;
        else
-               ret.type = im->sigt;
+               ret.type = tab->type;
        FLUSH(&ret);
 }
 
 // ifaceI2I(sigi *byte, iface any) (ret any);
-// called only for implicit (no type assertion) conversions
+// called only for implicit (no type assertion) conversions.
+// converting nil is okay.
 void
-sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
+sys·ifaceI2I(InterfaceType *inter, Iface i, Iface ret)
 {
-       Itype *im;
+       Itab *tab;
 
-       im = i.type;
-       if(im == nil) {
+       tab = i.tab;
+       if(tab == nil) {
                // If incoming interface is uninitialized (zeroed)
                // make the outgoing interface zeroed as well.
-               ret = niliface;
+               ret.tab = nil;
+               ret.data = nil;
        } else {
                ret = i;
-               if(im->sigi != si)
-                       ret.type = itype(si, im->sigt, 0);
+               if(tab->inter != inter)
+                       ret.tab = itab(inter, tab->type, 0);
        }
 
        FLUSH(&ret);
@@ -453,20 +328,21 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
 
 // ifaceI2Ix(sigi *byte, iface any) (ret any);
 // called only for explicit conversions (with type assertion).
+// converting nil is not okay.
 void
-sys·ifaceI2Ix(Sigi *si, Iface i, Iface ret)
+sys·ifaceI2Ix(InterfaceType *inter, Iface i, Iface ret)
 {
-       Itype *im;
+       Itab *tab;
 
-       im = i.type;
-       if(im == nil) {
+       tab = i.tab;
+       if(tab == nil) {
                // explicit conversions require non-nil interface value.
-               printf("interface is nil, not %s\n", si->name);
+               printf("interface is nil, not %S\n", *inter->string);
                throw("interface conversion");
        } else {
                ret = i;
-               if(im->sigi != si)
-                       ret.type = itype(si, im->sigt, 0);
+               if(tab->inter != inter)
+                       ret.tab = itab(inter, tab->type, 0);
        }
 
        FLUSH(&ret);
@@ -474,22 +350,23 @@ sys·ifaceI2Ix(Sigi *si, Iface i, Iface ret)
 
 // ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
 void
-sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
+sys·ifaceI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
 {
-       Itype *im;
+       Itab *tab;
 
-       im = i.type;
-       if(im == nil) {
+       tab = i.tab;
+       if(tab == nil) {
                // If incoming interface is nil, the conversion fails.
-               ret = niliface;
+               ret.tab = nil;
+               ret.data = nil;
                ok = false;
        } else {
                ret = i;
                ok = true;
-               if(im->sigi != si) {
-                       ret.type = itype(si, im->sigt, 1);
-                       if(ret.type == nil) {
-                               ret = niliface;
+               if(tab->inter != inter) {
+                       ret.tab = itab(inter, tab->type, 1);
+                       if(ret.tab == nil) {
+                               ret.data = nil;
                                ok = false;
                        }
                }
@@ -502,39 +379,40 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
 // ifaceE2I(sigi *byte, iface any) (ret any);
 // Called only for explicit conversions (with type assertion).
 void
-sys·ifaceE2I(Sigi *si, Eface e, Iface ret)
+sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
 {
-       Sigt *t;
+       Type *t;
 
        t = e.type;
        if(t == nil) {
                // explicit conversions require non-nil interface value.
-               printf("interface is nil, not %s\n", si->name);
+               printf("interface is nil, not %S\n", *inter->string);
                throw("interface conversion");
        } else {
                ret.data = e.data;
-               ret.type = itype(si, t, 0);
+               ret.tab = itab(inter, t, 0);
        }
        FLUSH(&ret);
 }
 
 // ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
 void
-sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
+sys·ifaceE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
 {
-       Sigt *t;
+       Type *t;
 
        t = e.type;
        ok = true;
        if(t == nil) {
                // If incoming interface is nil, the conversion fails.
-               ret = niliface;
+               ret.data = nil;
+               ret.tab = nil;
                ok = false;
        } else {
                ret.data = e.data;
-               ret.type = itype(si, t, 1);
-               if(ret.type == nil) {
-                       ret = niliface;
+               ret.tab = itab(inter, t, 1);
+               if(ret.tab == nil) {
+                       ret.data = nil;
                        ok = false;
                }
        }
@@ -543,19 +421,19 @@ sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
 }
 
 static uintptr
-ifacehash1(void *data, Sigt *sigt)
+ifacehash1(void *data, Type *t)
 {
        int32 alg, wid;
 
-       if(sigt == nil)
+       if(t == nil)
                return 0;
 
-       alg = sigt->alg;
-       wid = sigt->width;
+       alg = t->alg;
+       wid = t->size;
        if(algarray[alg].hash == nohash) {
                // calling nohash will throw too,
                // but we can print a better error.
-               printf("hash of unhashable type %s\n", sigt->name);
+               printf("hash of unhashable type %S\n", *t->string);
                if(alg == AFAKE)
                        throw("fake interface hash");
                throw("interface hash");
@@ -568,9 +446,9 @@ ifacehash1(void *data, Sigt *sigt)
 uintptr
 ifacehash(Iface a)
 {
-       if(a.type == nil)
+       if(a.tab == nil)
                return 0;
-       return ifacehash1(a.data, a.type->sigt);
+       return ifacehash1(a.data, a.tab->type);
 }
 
 uintptr
@@ -580,17 +458,17 @@ efacehash(Eface a)
 }
 
 static bool
-ifaceeq1(void *data1, void *data2, Sigt *sigt)
+ifaceeq1(void *data1, void *data2, Type *t)
 {
        int32 alg, wid;
 
-       alg = sigt->alg;
-       wid = sigt->width;
+       alg = t->alg;
+       wid = t->size;
 
        if(algarray[alg].equal == noequal) {
                // calling noequal will throw too,
                // but we can print a better error.
-               printf("comparing uncomparable type %s\n", sigt->name);
+               printf("comparing uncomparable type %S\n", *t->string);
                if(alg == AFAKE)
                        throw("fake interface compare");
                throw("interface compare");
@@ -604,11 +482,11 @@ ifaceeq1(void *data1, void *data2, Sigt *sigt)
 bool
 ifaceeq(Iface i1, Iface i2)
 {
-       if(i1.type != i2.type)
+       if(i1.tab != i2.tab)
                return false;
-       if(i1.type == nil)
+       if(i1.tab == nil)
                return true;
-       return ifaceeq1(i1.data, i2.data, i1.type->sigt);
+       return ifaceeq1(i1.data, i2.data, i1.tab->type);
 }
 
 bool
@@ -641,16 +519,12 @@ sys·efaceeq(Eface e1, Eface e2, bool ret)
 void
 sys·ifacethash(Iface i1, uint32 ret)
 {
-       Itype *im;
-       Sigt *st;
+       Itab *tab;
 
        ret = 0;
-       im = i1.type;
-       if(im != nil) {
-               st = im->sigt;
-               if(st != nil)
-                       ret = st->thash;
-       }
+       tab = i1.tab;
+       if(tab != nil)
+               ret = tab->type->hash;
        FLUSH(&ret);
 }
 
@@ -658,12 +532,12 @@ sys·ifacethash(Iface i1, uint32 ret)
 void
 sys·efacethash(Eface e1, uint32 ret)
 {
-       Sigt *st;
+       Type *t;
 
        ret = 0;
-       st = e1.type;
-       if(st != nil)
-               ret = st->thash;
+       t = e1.type;
+       if(t != nil)
+               ret = t->hash;
        FLUSH(&ret);
 }
 
@@ -680,227 +554,68 @@ sys·printeface(Eface e)
 }
 
 void
-unsafe·Reflect(Eface i, uint64 retit, String rettype, bool retindir)
-{
-       int32 wid;
-
-       if(i.type == nil) {
-               retit = 0;
-               rettype = emptystring;
-               retindir = false;
-       } else {
-               retit = (uint64)i.data;
-               rettype = gostring(i.type->name);
-               wid = i.type->width;
-               retindir = wid > sizeof(i.data);
-       }
-       FLUSH(&retit);
-       FLUSH(&rettype);
-       FLUSH(&retindir);
-}
-
-extern Sigt *gotypesigs[];
-extern int32 ngotypesigs;
-
-
-// The reflection library can ask to unreflect on a type
-// that has never been used, so we don't have a signature for it.
-// For concreteness, suppose a program does
-//
-//     type T struct{ x []int }
-//     var t T;
-//     v := reflect.NewValue(v);
-//     vv := v.Field(0);
-//     if s, ok := vv.Interface().(string) {
-//             print("first field is string");
-//     }
-//
-// vv.Interface() returns the result of sys.Unreflect with
-// a typestring of "[]int".  If []int is not used with interfaces
-// in the rest of the program, there will be no signature in gotypesigs
-// for "[]int", so we have to invent one.  The requirements
-// on the fake signature are:
-//
-//     (1) any interface conversion using the signature will fail
-//     (2) calling unsafe.Reflect() returns the args to unreflect
-//     (3) the right algorithm type is used, for == and map insertion
-//
-// (1) is ensured by the fact that we allocate a new Sigt,
-// so it will necessarily be != any Sigt in gotypesigs.
-// (2) is ensured by storing the type string in the signature
-// and setting the width to force the correct value of the bool indir.
-// (3) is ensured by sniffing the type string.
-//
-// Note that (1) is correct behavior: if the program had tested
-// for .([]int) instead of .(string) above, then there would be a
-// signature with type string "[]int" in gotypesigs, and unreflect
-// wouldn't call fakesigt.
-
-static Sigt*   fake[1009];
-static int32   nfake;
-
-enum
-{
-       SizeofInt = 4,
-       SizeofFloat = 4,
-};
-
-// Table of prefixes of names of comparable types.
-static struct {
-       int8 *s;
-       int8 n;
-       int8 alg;
-       int8 w;
-} cmp[] =
-{
-       // basic types
-       "int", 3+1, AMEM, SizeofInt, // +1 is NUL
-       "uint", 4+1, AMEM, SizeofInt,
-       "int8", 4+1, AMEM, 1,
-       "uint8", 5+1, AMEM, 1,
-       "int16", 5+1, AMEM, 2,
-       "uint16", 6+1, AMEM, 2,
-       "int32", 5+1, AMEM, 4,
-       "uint32", 6+1, AMEM, 4,
-       "int64", 5+1, AMEM, 8,
-       "uint64", 6+1, AMEM, 8,
-       "uintptr", 7+1, AMEM, sizeof(uintptr),
-       "float", 5+1, AMEM, SizeofFloat,
-       "float32", 7+1, AMEM, 4,
-       "float64", 7+1, AMEM, 8,
-       "bool", 4+1, AMEM, sizeof(bool),
-
-       // string compare is special
-       "string", 6+1, ASTRING, sizeof(String),
-
-       // generic types, identified by prefix
-       "*", 1, AMEM, sizeof(uintptr),
-       "chan ", 5, AMEM, sizeof(uintptr),
-       "func(", 5, AMEM, sizeof(uintptr),
-       "map[", 4, AMEM, sizeof(uintptr),
-};
-
-static Sigt*
-fakesigt(String type, bool indir)
-{
-       Sigt *sigt;
-       uint32 h;
-       int32 i, locked;
-
-       h = 0;
-       for(i=0; i<type.len; i++)
-               h = h*37 + type.str[i];
-       h += indir;
-       h %= nelem(fake);
-
-       for(locked=0; locked<2; locked++) {
-               if(locked)
-                       lock(&ifacelock);
-               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.
-                       if(mcmp(sigt->name, type.str, type.len) == 0)
-                       if(sigt->name[type.len] == '\0') {
-                               if(locked)
-                                       unlock(&ifacelock);
-                               return sigt;
-                       }
-               }
-       }
-
-       sigt = malloc(sizeof(*sigt));
-       sigt->name = malloc(type.len + 1);
-       mcpy(sigt->name, type.str, type.len);
-
-       sigt->alg = AFAKE;
-       sigt->width = 1;  // small width
-       if(indir)
-               sigt->width = 2*sizeof(niliface.data);  // big width
-
-       // AFAKE is like ANOEQ; check whether the type
-       // should have a more capable algorithm.
-       for(i=0; i<nelem(cmp); i++) {
-               if(mcmp((byte*)sigt->name, (byte*)cmp[i].s, cmp[i].n) == 0) {
-                       sigt->alg = cmp[i].alg;
-                       sigt->width = cmp[i].w;
-                       break;
-               }
-       }
-
-       sigt->link = fake[h];
-       fake[h] = sigt;
-
-       unlock(&ifacelock);
-       return sigt;
-}
-
-static int32
-cmpstringchars(String a, uint8 *b)
+unsafe·Typeof(Eface e, Eface ret)
 {
-       int32 i;
-       byte c1, c2;
-
-       for(i=0;; i++) {
-               c1 = 0;
-               if(i < a.len)
-                       c1 = a.str[i];
-               c2 = b[i];
-               if(c1 < c2)
-                       return -1;
-               if(c1 > c2)
-                       return +1;
-               if(c1 == 0)
-                       return 0;
-       }
+       if(e.type == nil) {
+               ret.type = nil;
+               ret.data = nil;
+       } else
+               ret = *(Eface*)e.type;
+       FLUSH(&ret);
 }
 
-static Sigt*
-findtype(String type, bool indir)
+void
+unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 {
-       int32 i, lo, hi, m;
+       uintptr *p;
+       uintptr x;
 
-       lo = 0;
-       hi = ngotypesigs;
-       while(lo < hi) {
-               m = lo + (hi - lo)/2;
-               i = cmpstringchars(type, gotypesigs[m]->name);
-               if(i == 0)
-                       return gotypesigs[m];
-               if(i < 0)
-                       hi = m;
-               else
-                       lo = m+1;
+       if(e.type == nil) {
+               rettype.type = nil;
+               rettype.data = nil;
+               retaddr = 0;
+       } else {
+               rettype = *(Eface*)e.type;
+               if(e.type->size <= sizeof(uintptr)) {
+                       // Copy data into x ...
+                       x = 0;
+                       algarray[e.type->alg].copy(e.type->size, &x, &e.data);
+
+                       // but then build pointer to x so that Reflect
+                       // always returns pointer to data.
+                       p = mallocgc(sizeof(uintptr));
+                       *p = x;
+               } else {
+                       // Already a pointer, but still make a copy,
+                       // to preserve value semantics for interface data.
+                       p = mallocgc(e.type->size);
+                       algarray[e.type->alg].copy(e.type->size, p, e.data);
+               }
+               retaddr = p;
        }
-       return fakesigt(type, indir);
+       FLUSH(&rettype);
+       FLUSH(&retaddr);
 }
 
-
 void
-unsafe·Unreflect(uint64 it, String type, bool indir, Eface ret)
-{
-       Sigt *sigt;
-
-       ret = nileface;
-
-       if(cmpstring(type, emptystring) == 0)
-               goto out;
-
-       if(type.len > 10 && mcmp(type.str, (byte*)"interface ", 10) == 0) {
-               printf("unsafe.Unreflect: cannot put %S in interface\n", type);
-               throw("unsafe.Unreflect");
+unsafe·Unreflect(Iface typ, void *addr, Eface e)
+{
+       // Reflect library has reinterpreted typ
+       // as its own kind of type structure.
+       // We know that the pointer to the original
+       // type structure sits before the data pointer.
+       e.type = (Type*)((Eface*)typ.data-1);
+
+       // Interface holds either pointer to data
+       // or copy of original data.
+       if(e.type->size <= sizeof(uintptr))
+               algarray[e.type->alg].copy(e.type->size, &e.data, addr);
+       else {
+               // Easier: already a pointer to data.
+               // TODO(rsc): Should this make a copy?
+               e.data = addr;
        }
 
-       // if we think the type should be indirect
-       // and caller does not, play it safe, return nil.
-       sigt = findtype(type, indir);
-       if(indir != (sigt->width > sizeof(ret.data)))
-               goto out;
-
-       ret.type = sigt;
-       ret.data = (void*)it;
-
-out:
-       FLUSH(&ret);
+       FLUSH(&e);
 }
 
index c7e09030e102d7284520e74589320524c5873a3b..c9929cd4543e2b29b4a4c179a44b2698c3fd1149 100644 (file)
@@ -76,10 +76,10 @@ printf(int8 *s, ...)
                        sys·printint(*(int64*)arg);
                        break;
                case 'x':
-                       sys·printhex(*(int32*)arg);
+                       sys·printhex(*(uint32*)arg);
                        break;
                case 'X':
-                       sys·printhex(*(int64*)arg);
+                       sys·printhex(*(uint64*)arg);
                        break;
                case 'p':
                        sys·printpointer(*(void**)arg);
index 8f1cfa73b878803148b1a5f27798c175d3b2c762..26dfe701677de5f45bd19d4b2fa24d10ee816f92 100644 (file)
@@ -56,9 +56,9 @@ typedef       struct  Usema           Usema;
 typedef        struct  SigTab          SigTab;
 typedef        struct  MCache          MCache;
 typedef        struct  Iface           Iface;
-typedef        struct  Itype           Itype;
+typedef        struct  Itab            Itab;
 typedef        struct  Eface   Eface;
-typedef        struct  Sigt            Sigt;
+typedef        struct  Type            Type;
 typedef        struct  Defer           Defer;
 
 /*
@@ -117,12 +117,12 @@ struct String
 };
 struct Iface
 {
-       Itype*  type;
+       Itab*   tab;
        void*   data;
 };
 struct Eface
 {
-       Sigt*           type;
+       Type*   type;
        void*   data;
 };