mirror of
https://github.com/golang/go
synced 2024-10-14 03:43:28 +00:00
change representation of interface values.
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
This commit is contained in:
parent
47e5152790
commit
2da5022bcf
|
@ -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"
|
||||
|
|
|
@ -43,6 +43,7 @@ enum
|
|||
ANOEQ,
|
||||
ASTRING,
|
||||
AINTER,
|
||||
ANILINTER,
|
||||
|
||||
BADWIDTH = -1000000000
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
if(iface_debug) {
|
||||
prints("I2T2 ret=");
|
||||
sys·printpointer(*(void**)ret);
|
||||
sys·printbool(*ok);
|
||||
prints("\n");
|
||||
|
||||
*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");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
uint64
|
||||
ifacehash(Iface a)
|
||||
// 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(a.type == nil)
|
||||
return 0;
|
||||
return ifacehash1(a.data, a.type->sigt);
|
||||
}
|
||||
|
||||
uint64
|
||||
efacehash(Eface a)
|
||||
{
|
||||
return ifacehash1(a.data, a.type);
|
||||
}
|
||||
|
||||
static bool
|
||||
ifaceeq1(void *data1, void *data2, Sigt *sigt)
|
||||
{
|
||||
int32 alg, wid;
|
||||
bool ret;
|
||||
|
||||
if(iface_debug) {
|
||||
prints("Ieq i1=");
|
||||
printiface(i1);
|
||||
prints(" i2=");
|
||||
printiface(i2);
|
||||
prints("\n");
|
||||
}
|
||||
|
||||
ret = false;
|
||||
|
||||
// are they both nil
|
||||
if(i1.type == nil) {
|
||||
if(i2.type == nil)
|
||||
goto yes;
|
||||
goto no;
|
||||
}
|
||||
if(i2.type == nil)
|
||||
goto no;
|
||||
|
||||
// are they the same type?
|
||||
if(i1.type->sigt != i2.type->sigt)
|
||||
goto no;
|
||||
|
||||
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·printinter(Iface i)
|
||||
sys·efacethash(Eface e1, uint32 ret)
|
||||
{
|
||||
Sigt *st;
|
||||
|
||||
ret = 0;
|
||||
st = e1.type;
|
||||
if(st != nil)
|
||||
ret = st->thash;
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
void
|
||||
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:
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue