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:
Russ Cox 2009-05-20 14:57:55 -07:00
parent 47e5152790
commit 2da5022bcf
10 changed files with 443 additions and 203 deletions

View 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"

View file

@ -43,6 +43,7 @@ enum
ANOEQ,
ASTRING,
AINTER,
ANILINTER,
BADWIDTH = -1000000000
};

View 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

View 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]);
t = sw->ntest->right->type;
if(isnilinter(t))
a = syslook("efacethash", 1);
else
a = syslook("ifacethash", 1);
argtype(a, sw->ntest->right->type);
argtype(a, t);
a = nod(OCALL, a, facename);
a = nod(OAS, hashname, a);
cas = list(cas, a);

View 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,

View 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);
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,6 +3096,11 @@ ifaceop(Type *tl, Node *n, int op)
a = n->left; // i1
r = list(a, r);
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);

View 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);
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);
copyin(st, elem, &ret->data);
}
if(iface_debug) {
prints("T2I ret=");
printiface(*ret);
prints("\n");
}
// ifaceT2E(sigt *byte, elem any) (ret any);
#pragma textflag 7
void
sys·ifaceT2E(Sigt *st, ...)
{
byte *elem;
Eface *ret;
int32 wid;
FLUSH(&ret);
elem = (byte*)(&st+1);
wid = st->width;
ret = (Eface*)(elem + rnd(wid, sizeof(uintptr)));
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 {
return;
}
*ok = true;
if(wid <= sizeof(i.data))
algarray[alg].copy(wid, ret, &i.data);
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
algarray[alg].copy(wid, ret, i.data);
}
if(iface_debug) {
prints("I2T2 ret=");
sys·printpointer(*(void**)ret);
sys·printbool(*ok);
prints("\n");
}
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");
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);
}
return ret;
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:

View 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 },
};

View 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*);

View 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