]> Cypherpunks repositories - gostls13.git/commitdiff
change representation of interface values.
authorRuss Cox <rsc@golang.org>
Wed, 20 May 2009 21:57:55 +0000 (14:57 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 20 May 2009 21:57:55 +0000 (14:57 -0700)
this is not a user-visible change.

before, all interface values were

struct Itype {
Sigt *type;
Sigi *inter;
void *method[n];
}

struct Iface {
void *addr;
Itype *itype;
}

the itype is basically a vtable, but it's unnecessary
if the static type is interface{ }.
for interface values with static type empty, the
new representation is

struct Eface {
void *addr;
Sigt *type;
}

this complicates the code somewhat, but
it reduces the number of Itypes that
have to be computed and cached,
it opens up opportunities to avoid function
calls in a few common cases,
and it will make it possible to lay out
interface{} values at compile time,
which i think i'll need for the new reflection.

R=ken
OCL=28701
CL=29121

src/cmd/gc/builtin.c.boot
src/cmd/gc/go.h
src/cmd/gc/subr.c
src/cmd/gc/swt.c
src/cmd/gc/sys.go
src/cmd/gc/walk.c
src/runtime/iface.c
src/runtime/runtime.c
src/runtime/runtime.h
test/golden.out

index 8506947e7065637598125a2f57e9819fbbf74a49..164a27822cb576f234eb324246758704e2dc76e7 100644 (file)
@@ -9,7 +9,8 @@ char *sysimport =
        "func sys.printint (? int64)\n"
        "func sys.printstring (? string)\n"
        "func sys.printpointer (? any)\n"
-       "func sys.printinter (? any)\n"
+       "func sys.printiface (? any)\n"
+       "func sys.printeface (? any)\n"
        "func sys.printarray (? any)\n"
        "func sys.printnl ()\n"
        "func sys.printsp ()\n"
@@ -21,13 +22,21 @@ char *sysimport =
        "func sys.arraystring (? []uint8) (? string)\n"
        "func sys.stringiter (? string, ? int) (? int)\n"
        "func sys.stringiter2 (? string, ? int) (retk int, retv int)\n"
+       "func sys.ifaceI2E (iface any) (ret any)\n"
+       "func sys.ifaceE2I (sigi *uint8, iface any) (ret any)\n"
+       "func sys.ifaceT2E (sigt *uint8, elem any) (ret any)\n"
+       "func sys.ifaceE2T (sigt *uint8, elem any) (ret any)\n"
+       "func sys.ifaceE2I2 (sigi *uint8, iface any) (ret any, ok bool)\n"
+       "func sys.ifaceE2T2 (sigt *uint8, elem any) (ret any, ok bool)\n"
        "func sys.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n"
        "func sys.ifaceI2T (sigt *uint8, iface any) (ret any)\n"
        "func sys.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n"
        "func sys.ifaceI2I (sigi *uint8, iface any) (ret any)\n"
        "func sys.ifaceI2I2 (sigi *uint8, iface any) (ret any, ok bool)\n"
        "func sys.ifaceeq (i1 any, i2 any) (ret bool)\n"
+       "func sys.efaceeq (i1 any, i2 any) (ret bool)\n"
        "func sys.ifacethash (i1 any) (ret uint32)\n"
+       "func sys.efacethash (i1 any) (ret uint32)\n"
        "func sys.newmap (keysize int, valsize int, keyalg int, valalg int, hint int) (hmap map[any] any)\n"
        "func sys.mapaccess1 (hmap map[any] any, key any) (val any)\n"
        "func sys.mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n"
index 267d12aa8e8e64405b08d010fc24d89d1560bbbd..763e2b555020e5d0d2f40c98716a1930787ebecf 100644 (file)
@@ -43,6 +43,7 @@ enum
        ANOEQ,
        ASTRING,
        AINTER,
+       ANILINTER,
 
        BADWIDTH        = -1000000000
 };
index 295a062ba620c1ced0e4c05a88ca3dc662be2407..38226a25c5d5a19daa5800a10d0fd8eb1a4b380b 100644 (file)
@@ -323,11 +323,11 @@ algtype(Type *t)
 
        if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN || t->etype == TFUNC)
                a = AMEM;       // just bytes (int, ptr, etc)
-       else
-       if(t->etype == TSTRING)
+       else if(t->etype == TSTRING)
                a = ASTRING;    // string
-       else
-       if(t->etype == TINTER)
+       else if(isnilinter(t))
+               a = ANILINTER;  // nil interface
+       else if(t->etype == TINTER)
                a = AINTER;     // interface
        else
                a = ANOEQ;      // just bytes, but no hash/eq
index 263496701f0210544791426e70729508d411b4ff..3f62706f70e3ec047afe865a8aaa27060be38a74 100644 (file)
@@ -762,6 +762,7 @@ typeswitch(Node *sw)
        Node *a;
        Case *c, *c0, *c1;
        int ncase;
+       Type *t;
 
        if(sw->ntest == nil)
                return;
@@ -793,8 +794,12 @@ typeswitch(Node *sw)
        hashname = nod(OXXX, N, N);
        tempname(hashname, types[TUINT32]);
 
-       a = syslook("ifacethash", 1);
-       argtype(a, sw->ntest->right->type);
+       t = sw->ntest->right->type;
+       if(isnilinter(t))
+               a = syslook("efacethash", 1);
+       else
+               a = syslook("ifacethash", 1);
+       argtype(a, t);
        a = nod(OCALL, a, facename);
        a = nod(OAS, hashname, a);
        cas = list(cas, a);
index 67fbb0391d7ab83c87d41284e4f6a94d676e9cbe..e139e759c603ccc91db3e559f3769f31e93c54e8 100644 (file)
@@ -17,7 +17,8 @@ func  printfloat(float64);
 func   printint(int64);
 func   printstring(string);
 func   printpointer(any);
-func   printinter(any);
+func   printiface(any);
+func   printeface(any);
 func   printarray(any);
 func   printnl();
 func   printsp();
@@ -31,13 +32,21 @@ func        arraystring([]byte) string;
 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   ifaceI2I2(sigi *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);
+func   efacethash(i1 any) (ret uint32);
 
 func   newmap(keysize int, valsize int,
                        keyalg int, valalg int,
index 3013faf19ee9c97d759a0d84a098db0a259b76dc..ea6dd8ced36cff6a755dacb273eea033308742a5 100644 (file)
@@ -15,6 +15,14 @@ enum
        I2I2,
        T2I,
        I2Isame,
+       E2T,
+       E2T2,
+       E2I,
+       E2I2,
+       I2E,
+       I2E2,
+       T2E,
+       E2Esame,
 };
 
 // can this code branch reach the end
@@ -444,6 +452,7 @@ loop:
                cr = listcount(r);
 
                if(cl == cr) {
+               simpleas:
                        walktype(r, Erv);
                        l = ascompatee(n->op, &n->left, &n->right);
                        if(l != N)
@@ -505,13 +514,25 @@ loop:
                                        break;
                                et = ifaceas1(r->type, r->left->type, 1);
                                switch(et) {
+                               case I2Isame:
+                               case E2Esame:
+                                       n->right = nod(OLIST, r->left, nodbool(1));
+                                       goto simpleas;
+                               case I2E:
+                                       n->right = nod(OLIST, n->right, nodbool(1));
+                                       goto simpleas;
                                case I2T:
                                        et = I2T2;
                                        break;
-                               case I2Isame:
                                case I2I:
                                        et = I2I2;
                                        break;
+                               case E2I:
+                                       et = E2I2;
+                                       break;
+                               case E2T:
+                                       et = E2T2;
+                                       break;
                                default:
                                        et = Inone;
                                        break;
@@ -1180,6 +1201,7 @@ void
 walkconv(Node *n)
 {
        int et;
+       char *what;
        Type *t;
        Node *l;
 
@@ -1199,9 +1221,13 @@ walkconv(Node *n)
                defaultlit(l, T);
                if(!isinter(l->type))
                        yyerror("type assertion requires interface on left, have %T", l->type);
-               et = ifaceas(n->type, l->type, 1);
+               et = ifaceas1(t, l->type, 1);
+               if(et == I2Isame || et == E2Esame) {
+                       n->op = OCONV;
+                       goto nop;
+               }
                if(et != Inone) {
-                       indir(n, ifaceop(n->type, l, et));
+                       indir(n, ifaceop(t, l, et));
                        return;
                }
                goto bad;
@@ -1212,8 +1238,9 @@ walkconv(Node *n)
        if(l->type == T)
                return;
 
-       // nil conversion
+       // no-op conversion
        if(cvttype(t, l->type)) {
+       nop:
                if(l->op != ONAME) {
                        indir(n, l);
                        n->type = t;
@@ -1267,9 +1294,9 @@ walkconv(Node *n)
 
        // convert from unsafe.pointer
        if(isptrto(l->type, TANY)) {
-               if(isptr[n->type->etype])
+               if(isptr[t->etype])
                        return;
-               if(n->type->etype == TUINTPTR)
+               if(t->etype == TUINTPTR)
                        return;
        }
 
@@ -1277,8 +1304,12 @@ bad:
        if(n->diag)
                return;
        n->diag = 1;
+       if(n->op == ODOTTYPE)
+               what = "type assertion";
+       else
+               what = "conversion";
        if(l->type != T)
-               yyerror("invalid conversion: %T to %T", l->type, t);
+               yyerror("invalid %s: %T to %T", what, l->type, t);
        else
        if(n->left->op == OLIST)
                yyerror("invalid type for composite literal: %T", t);
@@ -2095,7 +2126,10 @@ loop:
 
        et = l->type->etype;
        if(isinter(l->type)) {
-               on = syslook("printinter", 1);
+               if(isnilinter(l->type))
+                       on = syslook("printeface", 1);
+               else
+                       on = syslook("printiface", 1);
                argtype(on, l->type);           // any-1
        } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
                on = syslook("printpointer", 1);
@@ -2903,19 +2937,27 @@ ifaceas1(Type *dst, Type *src, int explicit)
 
        if(isinter(dst)) {
                if(isinter(src)) {
+                       if(isnilinter(dst)) {
+                               if(isnilinter(src))
+                                       return E2Esame;
+                               return I2E;
+                       }
                        if(eqtype(dst, src))
                                return I2Isame;
-                       if(!isnilinter(dst))
-                               ifacecheck(dst, src, lineno, explicit);
+                       ifacecheck(dst, src, lineno, explicit);
+                       if(isnilinter(src))
+                               return E2I;
                        return I2I;
                }
                if(isnilinter(dst))
-                       return T2I;
+                       return T2E;
                ifacecheck(dst, src, lineno, explicit);
                return T2I;
        }
        if(isinter(src)) {
                ifacecheck(dst, src, lineno, explicit);
+               if(isnilinter(src))
+                       return E2T;
                return I2T;
        }
        return Inone;
@@ -2930,7 +2972,7 @@ ifaceas(Type *dst, Type *src, int explicit)
        int et;
 
        et = ifaceas1(dst, src, explicit);
-       if(et == I2Isame)
+       if(et == I2Isame || et == E2Esame)
                et = Inone;
        return et;
 }
@@ -2943,6 +2985,15 @@ ifacename[] =
        [I2I]           = "ifaceI2I",
        [I2I2]          = "ifaceI2I2",
        [I2Isame]       = "ifaceI2Isame",
+       [E2T]           = "ifaceE2T",
+       [E2T2]          = "ifaceE2T2",
+       [E2I]           = "ifaceE2I",
+       [E2I2]          = "ifaceE2I2",
+       [I2E]           = "ifaceI2E",
+       [I2E2]          = "ifaceI2E2",
+       [T2I]           = "ifaceT2I",
+       [T2E]           = "ifaceT2E",
+       [E2Esame]       = "ifaceE2Esame",
 };
 
 Node*
@@ -2982,19 +3033,21 @@ ifaceop(Type *tl, Node *n, int op)
                on = syslook("ifaceT2I", 1);
                argtype(on, tr);
                argtype(on, tl);
-
                break;
 
        case I2T:
        case I2T2:
        case I2I:
        case I2I2:
+       case E2T:
+       case E2T2:
+       case E2I:
+       case E2I2:
                // iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]);
-
                a = n;                          // interface
                r = a;
 
-               s = signame(tl);                // sigi
+               s = signame(tl);                // sigi or sigt
                if(s == S)
                        fatal("ifaceop: signame %d", op);
                a = s->oname;
@@ -3004,7 +3057,34 @@ ifaceop(Type *tl, Node *n, int op)
                on = syslook(ifacename[op], 1);
                argtype(on, tr);
                argtype(on, tl);
+               break;
 
+       case I2E:
+               // TODO(rsc): Should do this in back end, without a call.
+               // ifaceI2E(elem any) (ret any);
+               a = n;                          // interface
+               r = a;
+               on = syslook("ifaceI2E", 1);
+               argtype(on, tr);
+               argtype(on, tl);
+               break;
+
+       case T2E:
+               // TODO(rsc): Should do this in back end for pointer case, without a call.
+               // ifaceT2E(sigt *byte, elem any) (ret any);
+               a = n;                          // elem
+               r = a;
+
+               s = signame(tr);                // sigt
+               if(s == S)
+                       fatal("ifaceop: signame-1 T2E: %lT", tr);
+               a = s->oname;
+               a = nod(OADDR, a, N);
+               r = list(a, r);
+
+               on = syslook("ifaceT2E", 1);
+               argtype(on, tr);
+               argtype(on, tl);
                break;
 
        case OEQ:
@@ -3016,7 +3096,12 @@ ifaceop(Type *tl, Node *n, int op)
                a = n->left;                            // i1
                r = list(a, r);
 
-               on = syslook("ifaceeq", 1);
+               if(!eqtype(n->left->type, n->right->type))
+                       fatal("ifaceop %O %T %T", op, n->left->type, n->right->type);
+               if(isnilinter(n->left->type))
+                       on = syslook("efaceeq", 1);
+               else
+                       on = syslook("ifaceeq", 1);
                argtype(on, n->right->type);
                argtype(on, n->left->type);
 
index cad7370c5f8493f9b36f8e76c3d566dc15fc754d..9e65a267aa0144357c66105220f3a2c07a827e06 100644 (file)
@@ -53,6 +53,8 @@ struct        Itype
 };
 
 static Iface   niliface;
+static Eface   nileface;
+
 static Itype*  hash[1009];
 static Lock    ifacelock;
 
@@ -129,6 +131,16 @@ printiface(Iface i)
        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)
 {
@@ -138,6 +150,17 @@ itype(Sigi *si, Sigt *st, int32 canfail)
        byte *sname, *iname;
        Itype *m;
 
+       if(si->size == 0)
+               throw("internal error - misuse of itype");
+
+       // easy case
+       if(st->meth[0].fname == nil) {
+               if(canfail)
+                       return nil;
+               iname = si->meth[0].fname;
+               goto throw1;
+       }
+
        // compiler has provided some good hash codes for us.
        h = 0;
        if(si)
@@ -169,7 +192,6 @@ itype(Sigi *si, Sigt *st, int32 canfail)
                                                goto throw;
                                        }
                                }
-                               // prints("old itype\n");
                                if(locked)
                                        unlock(&ifacelock);
                                return m;
@@ -199,6 +221,7 @@ throw:
                        sname = st->meth[nt].fname;
                        if(sname == nil) {
                                if(!canfail) {
+                               throw1:
                                        printf("cannot convert type %s to interface %s: missing method %s\n",
                                                st->name, si->name, iname);
                                        if(iface_debug) {
@@ -209,6 +232,7 @@ throw:
                                                prints("\n");
                                        }
                                        throw("interface conversion");
+                                       return nil;     // not reached
                                }
                                m->bad = 1;
                                m->link = hash[h];
@@ -227,124 +251,108 @@ throw:
        if(locked)
                unlock(&ifacelock);
 
-       // printf("new itype %p\n", m);
        return m;
 }
 
+static void
+copyin(Sigt *st, void *src, void **dst)
+{
+       int32 wid, alg;
+       void *p;
+
+       wid = st->width;
+       alg = st->alg;
+
+       if(wid <= sizeof(*dst))
+               algarray[alg].copy(wid, dst, src);
+       else {
+               p = mal(wid);
+               algarray[alg].copy(wid, p, src);
+               *dst = p;
+       }
+}
+
+static void
+copyout(Sigt *st, void **src, void *dst)
+{
+       int32 wid, alg;
+
+       wid = st->width;
+       alg = st->alg;
+
+       if(wid <= sizeof(*src))
+               algarray[alg].copy(wid, dst, src);
+       else
+               algarray[alg].copy(wid, dst, *src);
+}
+
 // ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
+#pragma textflag 7
 void
 sys·ifaceT2I(Sigi *si, Sigt *st, ...)
 {
        byte *elem;
        Iface *ret;
-       int32 alg, wid;
+       int32 wid;
 
        elem = (byte*)(&st+1);
-
-       if(iface_debug) {
-               prints("T2I sigi=");
-               printsigi(si);
-               prints(" sigt=");
-               printsigt(st);
-               prints(" elem=");
-               sys·printpointer(*(void**)elem);
-               prints("\n");
-       }
-
        wid = st->width;
-       alg = st->alg;
        ret = (Iface*)(elem + rnd(wid, sizeof(uintptr)));
+
        ret->type = itype(si, st, 0);
+       copyin(st, elem, &ret->data);
+}
 
-       if(wid <= sizeof(ret->data))
-               algarray[alg].copy(wid, &ret->data, elem);
-       else {
-               ret->data = mal(wid);
-               if(iface_debug)
-                       printf("T2I mal %d %p\n", wid, ret->data);
-               algarray[alg].copy(wid, ret->data, elem);
-       }
+// ifaceT2E(sigt *byte, elem any) (ret any);
+#pragma textflag 7
+void
+sys·ifaceT2E(Sigt *st, ...)
+{
+       byte *elem;
+       Eface *ret;
+       int32 wid;
 
-       if(iface_debug) {
-               prints("T2I ret=");
-               printiface(*ret);
-               prints("\n");
-       }
+       elem = (byte*)(&st+1);
+       wid = st->width;
+       ret = (Eface*)(elem + rnd(wid, sizeof(uintptr)));
 
-       FLUSH(&ret);
+       ret->type = st;
+       copyin(st, elem, &ret->data);
 }
 
 // ifaceI2T(sigt *byte, iface any) (ret any);
+#pragma textflag 7
 void
 sys·ifaceI2T(Sigt *st, Iface i, ...)
 {
        Itype *im;
        byte *ret;
-       int32 wid, alg;
 
        ret = (byte*)(&i+1);
 
-       if(iface_debug) {
-               prints("I2T sigt=");
-               printsigt(st);
-               prints(" iface=");
-               printiface(i);
-               prints("\n");
-       }
-
        im = i.type;
        if(im == nil) {
-               prints("interface is nil, not ");
-               prints((int8*)st->name);
-               prints("\n");
+               printf("interface is nil, not %s\n", st->name);
                throw("interface conversion");
        }
-
        if(im->sigt != st) {
-               prints((int8*)im->sigi->name);
-               prints(" is ");
-               prints((int8*)im->sigt->name);
-               prints(", not ");
-               prints((int8*)st->name);
-               prints("\n");
+               printf("%s is %s, not %s\n", im->sigi->name, im->sigt->name, st->name);
                throw("interface conversion");
        }
-
-       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);
-
-       if(iface_debug) {
-               prints("I2T ret=");
-               sys·printpointer(*(void**)ret);
-               prints("\n");
-       }
-       FLUSH(&ret);
+       copyout(st, &i.data, ret);
 }
 
 // ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
+#pragma textflag 7
 void
 sys·ifaceI2T2(Sigt *st, Iface i, ...)
 {
        byte *ret;
        bool *ok;
        Itype *im;
-       int32 alg, wid;
-
-
-       if(iface_debug) {
-               prints("I2T2 sigt=");
-               printsigt(st);
-               prints(" iface=");
-               printiface(i);
-               prints("\n");
-       }
+       int32 wid;
 
        ret = (byte*)(&i+1);
-       alg = st->alg;
        wid = st->width;
        ok = (bool*)(ret+rnd(wid, 1));
 
@@ -352,19 +360,74 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...)
        if(im == nil || im->sigt != st) {
                *ok = false;
                sys·memclr(ret, wid);
-       } else {
-               *ok = true;
-               if(wid <= sizeof(i.data))
-                       algarray[alg].copy(wid, ret, &i.data);
-               else
-                       algarray[alg].copy(wid, ret, i.data);
+               return;
+       }
+
+       *ok = true;
+       copyout(st, &i.data, ret);
+}
+
+// ifaceE2T(sigt *byte, iface any) (ret any);
+#pragma textflag 7
+void
+sys·ifaceE2T(Sigt *st, 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);
+               throw("interface conversion");
        }
-       if(iface_debug) {
-               prints("I2T2 ret=");
-               sys·printpointer(*(void**)ret);
-               sys·printbool(*ok);
-               prints("\n");
+       copyout(st, &e.data, ret);
+}
+
+// ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
+#pragma textflag 7
+void
+sys·ifaceE2T2(Sigt *st, Eface e, ...)
+{
+       byte *ret;
+       bool *ok;
+       Sigt *t;
+       int32 wid;
+
+       ret = (byte*)(&e+1);
+       wid = st->width;
+       ok = (bool*)(ret+rnd(wid, 1));
+
+       t = e.type;
+       if(t != st) {
+               *ok = false;
+               sys·memclr(ret, wid);
+               return;
        }
+
+       *ok = true;
+       copyout(st, &e.data, ret);
+}
+
+// ifaceI2E(sigi *byte, iface any) (ret any);
+// TODO(rsc): Move to back end, throw away function.
+void
+sys·ifaceI2E(Iface i, Eface ret)
+{
+       Itype *im;
+
+       ret.data = i.data;
+       im = i.type;
+       if(im == nil)
+               ret.type = nil;
+       else
+               ret.type = im->sigt;
+       FLUSH(&ret);
 }
 
 // ifaceI2I(sigi *byte, iface any) (ret any);
@@ -373,16 +436,9 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
 {
        Itype *im;
 
-       if(iface_debug) {
-               prints("I2I sigi=");
-               printsigi(si);
-               prints(" iface=");
-               printiface(i);
-               prints("\n");
-       }
-
        im = i.type;
        if(im == nil) {
+//TODO(rsc): fixme
                // If incoming interface is uninitialized (zeroed)
                // make the outgoing interface zeroed as well.
                ret = niliface;
@@ -392,12 +448,6 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
                        ret.type = itype(si, im->sigt, 0);
        }
 
-       if(iface_debug) {
-               prints("I2I ret=");
-               printiface(ret);
-               prints("\n");
-       }
-
        FLUSH(&ret);
 }
 
@@ -407,52 +457,76 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
 {
        Itype *im;
 
-       if(iface_debug) {
-               prints("I2I2 sigi=");
-               printsigi(si);
-               prints(" iface=");
-               printiface(i);
-               prints("\n");
-       }
-
        im = i.type;
+       ok = true;
        if(im == nil) {
+//TODO: fixme
                // If incoming interface is uninitialized (zeroed)
                // make the outgoing interface zeroed as well.
                ret = niliface;
-               ok = 1;
        } else {
                ret = i;
-               ok = 1;
                if(im->sigi != si) {
                        ret.type = itype(si, im->sigt, 1);
                        if(ret.type == nil) {
                                ret = niliface;
-                               ok = 0;
+                               ok = false;
                        }
                }
        }
 
-       if(iface_debug) {
-               prints("I2I ret=");
-               printiface(ret);
-               prints("\n");
+       FLUSH(&ret);
+       FLUSH(&ok);
+}
+
+// ifaceE2I(sigi *byte, iface any) (ret any);
+void
+sys·ifaceE2I(Sigi *si, Eface e, Iface ret)
+{
+       Sigt *t;
+
+       t = e.type;
+       if(t == nil) {
+//TODO(rsc): fixme
+               ret = niliface;
+       } else {
+               ret.data = e.data;
+               ret.type = itype(si, t, 0);
        }
+       FLUSH(&ret);
+}
+
+// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
+void
+sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
+{
+       Sigt *t;
 
+       t = e.type;
+       ok = true;
+       if(t == nil) {
+//TODO(rsc): fixme
+               ret = niliface;
+       } else {
+               ret.data = e.data;
+               ret.type = itype(si, t, 1);
+               if(ret.type == nil) {
+                       ret = niliface;
+                       ok = false;
+               }
+       }
        FLUSH(&ret);
        FLUSH(&ok);
 }
 
-uint64
-ifacehash(Iface a)
+static uint64
+ifacehash1(void *data, Sigt *sigt)
 {
        int32 alg, wid;
-       Sigt *sigt;
 
-       if(a.type == nil)
+       if(sigt == nil)
                return 0;
 
-       sigt = a.type->sigt;
        alg = sigt->alg;
        wid = sigt->width;
        if(algarray[alg].hash == nohash) {
@@ -463,69 +537,65 @@ ifacehash(Iface a)
                        throw("fake interface hash");
                throw("interface hash");
        }
-       if(wid <= sizeof(a.data))
-               return algarray[alg].hash(wid, &a.data);
-       return algarray[alg].hash(wid, a.data);
+       if(wid <= sizeof(data))
+               return algarray[alg].hash(wid, &data);
+       return algarray[alg].hash(wid, data);
 }
 
-bool
-ifaceeq(Iface i1, Iface i2)
+uint64
+ifacehash(Iface a)
 {
-       int32 alg, wid;
-       bool ret;
-
-       if(iface_debug) {
-               prints("Ieq i1=");
-               printiface(i1);
-               prints(" i2=");
-               printiface(i2);
-               prints("\n");
-       }
-
-       ret = false;
+       if(a.type == nil)
+               return 0;
+       return ifacehash1(a.data, a.type->sigt);
+}
 
-       // are they both nil
-       if(i1.type == nil) {
-               if(i2.type == nil)
-                       goto yes;
-               goto no;
-       }
-       if(i2.type == nil)
-               goto no;
+uint64
+efacehash(Eface a)
+{
+       return ifacehash1(a.data, a.type);
+}
 
-       // are they the same type?
-       if(i1.type->sigt != i2.type->sigt)
-               goto no;
+static bool
+ifaceeq1(void *data1, void *data2, Sigt *sigt)
+{
+       int32 alg, wid;
 
-       alg = i1.type->sigt->alg;
-       wid = i1.type->sigt->width;
+       alg = sigt->alg;
+       wid = sigt->width;
 
        if(algarray[alg].equal == noequal) {
                // calling noequal will throw too,
                // but we can print a better error.
-               printf("comparing uncomparable type %s\n", i1.type->sigt->name);
+               printf("comparing uncomparable type %s\n", sigt->name);
                if(alg == AFAKE)
                        throw("fake interface compare");
                throw("interface compare");
        }
 
-       if(wid <= sizeof(i1.data)) {
-               if(!algarray[alg].equal(wid, &i1.data, &i2.data))
-                       goto no;
-       } else {
-               if(!algarray[alg].equal(wid, i1.data, i2.data))
-                       goto no;
-       }
+       if(wid <= sizeof(data1))
+               return algarray[alg].equal(wid, &data1, &data2);
+       return algarray[alg].equal(wid, data1, data2);
+}
 
-yes:
-       ret = true;
-no:
-       if(iface_debug) {
-               prints("Ieq ret=");
-               sys·printbool(ret);
-               prints("\n");
-       }
-       return ret;
+bool
+ifaceeq(Iface i1, Iface i2)
+{
+       if(i1.type != i2.type)
+               return false;
+       if(i1.type == nil)
+               return true;
+       return ifaceeq1(i1.data, i2.data, i1.type->sigt);
+}
+
+bool
+efaceeq(Eface e1, Eface e2)
+{
+       if(e1.type != e2.type)
+               return false;
+       if(e1.type == nil)
+               return true;
+       return ifaceeq1(e1.data, e2.data, e1.type);
 }
 
 // ifaceeq(i1 any, i2 any) (ret bool);
@@ -536,6 +606,14 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret)
        FLUSH(&ret);
 }
 
+// efaceeq(i1 any, i2 any) (ret bool)
+void
+sys·efaceeq(Eface e1, Eface e2, bool ret)
+{
+       ret = efaceeq(e1, e2);
+       FLUSH(&ret);
+}
+
 // ifacethash(i1 any) (ret uint32);
 void
 sys·ifacethash(Iface i1, uint32 ret)
@@ -553,14 +631,33 @@ sys·ifacethash(Iface i1, uint32 ret)
        FLUSH(&ret);
 }
 
+// efacethash(e1 any) (ret uint32)
+void
+sys·efacethash(Eface e1, uint32 ret)
+{
+       Sigt *st;
+
+       ret = 0;
+       st = e1.type;
+       if(st != nil)
+               ret = st->thash;
+       FLUSH(&ret);
+}
+
 void
-sys·printinter(Iface i)
+sys·printiface(Iface i)
 {
        printiface(i);
 }
 
 void
-unsafe·Reflect(Iface i, uint64 retit, String rettype, bool retindir)
+sys·printeface(Eface e)
+{
+       printeface(e);
+}
+
+void
+unsafe·Reflect(Eface i, uint64 retit, String rettype, bool retindir)
 {
        int32 wid;
 
@@ -570,8 +667,8 @@ unsafe·Reflect(Iface i, uint64 retit, String rettype, bool retindir)
                retindir = false;
        } else {
                retit = (uint64)i.data;
-               rettype = gostring(i.type->sigt->name);
-               wid = i.type->sigt->width;
+               rettype = gostring(i.type->name);
+               wid = i.type->width;
                retindir = wid > sizeof(i.data);
        }
        FLUSH(&retit);
@@ -757,11 +854,11 @@ findtype(String type, bool indir)
 
 
 void
-unsafe·Unreflect(uint64 it, String type, bool indir, Iface ret)
+unsafe·Unreflect(uint64 it, String type, bool indir, Eface ret)
 {
        Sigt *sigt;
 
-       ret = niliface;
+       ret = nileface;
 
        if(cmpstring(type, emptystring) == 0)
                goto out;
@@ -777,7 +874,7 @@ unsafe·Unreflect(uint64 it, String type, bool indir, Iface ret)
        if(indir != (sigt->width > sizeof(ret.data)))
                goto out;
 
-       ret.type = itype(sigi·empty, sigt, 0);
+       ret.type = sigt;
        ret.data = (void*)it;
 
 out:
index afb9cce172219feced554c3ab4fd94f768bc9073..57e2570905bc689eccd05744141011954b2fe404 100644 (file)
@@ -363,7 +363,7 @@ static void
 interprint(uint32 s, Iface *a)
 {
        USED(s);
-       sys·printinter(*a);
+       sys·printiface(*a);
 }
 
 static uint32
@@ -373,6 +373,27 @@ interequal(uint32 s, Iface *a, Iface *b)
        return ifaceeq(*a, *b);
 }
 
+static uint64
+nilinterhash(uint32 s, Eface *a)
+{
+       USED(s);
+       return efacehash(*a);
+}
+
+static void
+nilinterprint(uint32 s, Eface *a)
+{
+       USED(s);
+       sys·printeface(*a);
+}
+
+static uint32
+nilinterequal(uint32 s, Eface *a, Eface *b)
+{
+       USED(s);
+       return efaceeq(*a, *b);
+}
+
 uint64
 nohash(uint32 s, void *a)
 {
@@ -416,6 +437,7 @@ algarray[] =
 [ANOEQ]        { nohash, noequal, memprint, memcopy },
 [ASTRING]      { strhash, strequal, strprint, memcopy },
 [AINTER]               { interhash, interequal, interprint, memcopy },
+[ANILINTER]    { nilinterhash, nilinterequal, nilinterprint, memcopy },
 [AFAKE]        { nohash, noequal, noprint, nocopy },
 };
 
index 68d3748f37dfc81afa7475830525aa05db22c291..f2926037aa4e71cbe6164209e707dc090401067a 100644 (file)
@@ -57,6 +57,8 @@ typedef       struct  SigTab          SigTab;
 typedef        struct  MCache          MCache;
 typedef        struct  Iface           Iface;
 typedef        struct  Itype           Itype;
+typedef        struct  Eface   Eface;
+typedef        struct  Sigt            Sigt;
 typedef        struct  Defer           Defer;
 
 /*
@@ -118,6 +120,11 @@ struct Iface
        Itype*  type;
        void*   data;
 };
+struct Eface
+{
+       Sigt*           type;
+       void*   data;
+};
 
 struct Array
 {                              // must not move anything
@@ -238,6 +245,7 @@ enum
        ANOEQ,
        ASTRING,
        AINTER,
+       ANILINTER,
        AFAKE,
        Amax
 };
@@ -323,7 +331,9 @@ void        stackfree(void*);
 MCache*        allocmcache(void);
 void   mallocinit(void);
 bool   ifaceeq(Iface, Iface);
+bool   efaceeq(Eface, Eface);
 uint64 ifacehash(Iface);
+uint64 efacehash(Eface);
 uint64 nohash(uint32, void*);
 uint32 noequal(uint32, void*, void*);
 void*  malloc(uintptr size);
@@ -396,7 +406,8 @@ void        notewakeup(Note*);
 #define sys_printfloat sys·printfloat
 #define sys_printhex sys·printhex
 #define sys_printint sys·printint
-#define sys_printinter sys·printinter
+#define sys_printiface sys·printiface
+#define sys_printeface sys·printeface
 #define sys_printpc sys·printpc
 #define sys_printpointer sys·printpointer
 #define sys_printstring sys·printstring
@@ -420,7 +431,8 @@ void*       sys_getcallerpc(void*);
 void   sys_printbool(bool);
 void   sys_printfloat(float64);
 void   sys_printint(int64);
-void   sys_printinter(Iface);
+void   sys_printiface(Iface);
+void   sys_printeface(Eface);
 void   sys_printstring(String);
 void   sys_printpc(void*);
 void   sys_printpointer(void*);
index 8258f621d62d6803f95f01ff5689c53680bff4fa..aaef7c3073812ba50224829c1938031926a26e33 100644 (file)
@@ -225,7 +225,7 @@ fixedbugs/bug103.go:8: illegal types for operand: AS
        int
 
 =========== fixedbugs/bug113.go
-main.I is int, not int32
+interface is int, not int32
 throw: interface conversion
 
 panic PC=xxx