Commit 2da5022b authored by Russ Cox's avatar Russ Cox

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
parent 47e51527
...@@ -9,7 +9,8 @@ char *sysimport = ...@@ -9,7 +9,8 @@ char *sysimport =
"func sys.printint (? int64)\n" "func sys.printint (? int64)\n"
"func sys.printstring (? string)\n" "func sys.printstring (? string)\n"
"func sys.printpointer (? any)\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.printarray (? any)\n"
"func sys.printnl ()\n" "func sys.printnl ()\n"
"func sys.printsp ()\n" "func sys.printsp ()\n"
...@@ -21,13 +22,21 @@ char *sysimport = ...@@ -21,13 +22,21 @@ char *sysimport =
"func sys.arraystring (? []uint8) (? string)\n" "func sys.arraystring (? []uint8) (? string)\n"
"func sys.stringiter (? string, ? int) (? int)\n" "func sys.stringiter (? string, ? int) (? int)\n"
"func sys.stringiter2 (? string, ? int) (retk int, retv 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.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n"
"func sys.ifaceI2T (sigt *uint8, iface 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.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceI2I (sigi *uint8, iface any) (ret any)\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.ifaceI2I2 (sigi *uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceeq (i1 any, i2 any) (ret 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.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.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.mapaccess1 (hmap map[any] any, key any) (val any)\n"
"func sys.mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n" "func sys.mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n"
......
...@@ -43,6 +43,7 @@ enum ...@@ -43,6 +43,7 @@ enum
ANOEQ, ANOEQ,
ASTRING, ASTRING,
AINTER, AINTER,
ANILINTER,
BADWIDTH = -1000000000 BADWIDTH = -1000000000
}; };
......
...@@ -323,11 +323,11 @@ algtype(Type *t) ...@@ -323,11 +323,11 @@ algtype(Type *t)
if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN || t->etype == TFUNC) if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN || t->etype == TFUNC)
a = AMEM; // just bytes (int, ptr, etc) a = AMEM; // just bytes (int, ptr, etc)
else else if(t->etype == TSTRING)
if(t->etype == TSTRING)
a = ASTRING; // string a = ASTRING; // string
else else if(isnilinter(t))
if(t->etype == TINTER) a = ANILINTER; // nil interface
else if(t->etype == TINTER)
a = AINTER; // interface a = AINTER; // interface
else else
a = ANOEQ; // just bytes, but no hash/eq a = ANOEQ; // just bytes, but no hash/eq
......
...@@ -762,6 +762,7 @@ typeswitch(Node *sw) ...@@ -762,6 +762,7 @@ typeswitch(Node *sw)
Node *a; Node *a;
Case *c, *c0, *c1; Case *c, *c0, *c1;
int ncase; int ncase;
Type *t;
if(sw->ntest == nil) if(sw->ntest == nil)
return; return;
...@@ -793,8 +794,12 @@ typeswitch(Node *sw) ...@@ -793,8 +794,12 @@ typeswitch(Node *sw)
hashname = nod(OXXX, N, N); hashname = nod(OXXX, N, N);
tempname(hashname, types[TUINT32]); tempname(hashname, types[TUINT32]);
a = syslook("ifacethash", 1); t = sw->ntest->right->type;
argtype(a, 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(OCALL, a, facename);
a = nod(OAS, hashname, a); a = nod(OAS, hashname, a);
cas = list(cas, a); cas = list(cas, a);
......
...@@ -17,7 +17,8 @@ func printfloat(float64); ...@@ -17,7 +17,8 @@ func printfloat(float64);
func printint(int64); func printint(int64);
func printstring(string); func printstring(string);
func printpointer(any); func printpointer(any);
func printinter(any); func printiface(any);
func printeface(any);
func printarray(any); func printarray(any);
func printnl(); func printnl();
func printsp(); func printsp();
...@@ -31,13 +32,21 @@ func arraystring([]byte) string; ...@@ -31,13 +32,21 @@ func arraystring([]byte) string;
func stringiter(string, int) int; func stringiter(string, int) int;
func stringiter2(string, int) (retk int, retv 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 ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
func ifaceI2T(sigt *byte, iface any) (ret any); func ifaceI2T(sigt *byte, iface any) (ret any);
func ifaceI2T2(sigt *byte, iface any) (ret any, ok bool); func ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
func ifaceI2I(sigi *byte, iface any) (ret any); func ifaceI2I(sigi *byte, iface any) (ret any);
func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool); func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
func ifaceeq(i1 any, i2 any) (ret bool); func ifaceeq(i1 any, i2 any) (ret bool);
func efaceeq(i1 any, i2 any) (ret bool);
func ifacethash(i1 any) (ret uint32); func ifacethash(i1 any) (ret uint32);
func efacethash(i1 any) (ret uint32);
func newmap(keysize int, valsize int, func newmap(keysize int, valsize int,
keyalg int, valalg int, keyalg int, valalg int,
......
...@@ -15,6 +15,14 @@ enum ...@@ -15,6 +15,14 @@ enum
I2I2, I2I2,
T2I, T2I,
I2Isame, I2Isame,
E2T,
E2T2,
E2I,
E2I2,
I2E,
I2E2,
T2E,
E2Esame,
}; };
// can this code branch reach the end // can this code branch reach the end
...@@ -444,6 +452,7 @@ loop: ...@@ -444,6 +452,7 @@ loop:
cr = listcount(r); cr = listcount(r);
if(cl == cr) { if(cl == cr) {
simpleas:
walktype(r, Erv); walktype(r, Erv);
l = ascompatee(n->op, &n->left, &n->right); l = ascompatee(n->op, &n->left, &n->right);
if(l != N) if(l != N)
...@@ -505,13 +514,25 @@ loop: ...@@ -505,13 +514,25 @@ loop:
break; break;
et = ifaceas1(r->type, r->left->type, 1); et = ifaceas1(r->type, r->left->type, 1);
switch(et) { 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: case I2T:
et = I2T2; et = I2T2;
break; break;
case I2Isame:
case I2I: case I2I:
et = I2I2; et = I2I2;
break; break;
case E2I:
et = E2I2;
break;
case E2T:
et = E2T2;
break;
default: default:
et = Inone; et = Inone;
break; break;
...@@ -1180,6 +1201,7 @@ void ...@@ -1180,6 +1201,7 @@ void
walkconv(Node *n) walkconv(Node *n)
{ {
int et; int et;
char *what;
Type *t; Type *t;
Node *l; Node *l;
...@@ -1199,9 +1221,13 @@ walkconv(Node *n) ...@@ -1199,9 +1221,13 @@ walkconv(Node *n)
defaultlit(l, T); defaultlit(l, T);
if(!isinter(l->type)) if(!isinter(l->type))
yyerror("type assertion requires interface on left, have %T", 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) { if(et != Inone) {
indir(n, ifaceop(n->type, l, et)); indir(n, ifaceop(t, l, et));
return; return;
} }
goto bad; goto bad;
...@@ -1212,8 +1238,9 @@ walkconv(Node *n) ...@@ -1212,8 +1238,9 @@ walkconv(Node *n)
if(l->type == T) if(l->type == T)
return; return;
// nil conversion // no-op conversion
if(cvttype(t, l->type)) { if(cvttype(t, l->type)) {
nop:
if(l->op != ONAME) { if(l->op != ONAME) {
indir(n, l); indir(n, l);
n->type = t; n->type = t;
...@@ -1267,9 +1294,9 @@ walkconv(Node *n) ...@@ -1267,9 +1294,9 @@ walkconv(Node *n)
// convert from unsafe.pointer // convert from unsafe.pointer
if(isptrto(l->type, TANY)) { if(isptrto(l->type, TANY)) {
if(isptr[n->type->etype]) if(isptr[t->etype])
return; return;
if(n->type->etype == TUINTPTR) if(t->etype == TUINTPTR)
return; return;
} }
...@@ -1277,8 +1304,12 @@ bad: ...@@ -1277,8 +1304,12 @@ bad:
if(n->diag) if(n->diag)
return; return;
n->diag = 1; n->diag = 1;
if(n->op == ODOTTYPE)
what = "type assertion";
else
what = "conversion";
if(l->type != T) if(l->type != T)
yyerror("invalid conversion: %T to %T", l->type, t); yyerror("invalid %s: %T to %T", what, l->type, t);
else else
if(n->left->op == OLIST) if(n->left->op == OLIST)
yyerror("invalid type for composite literal: %T", t); yyerror("invalid type for composite literal: %T", t);
...@@ -2095,7 +2126,10 @@ loop: ...@@ -2095,7 +2126,10 @@ loop:
et = l->type->etype; et = l->type->etype;
if(isinter(l->type)) { 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 argtype(on, l->type); // any-1
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) { } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
on = syslook("printpointer", 1); on = syslook("printpointer", 1);
...@@ -2903,19 +2937,27 @@ ifaceas1(Type *dst, Type *src, int explicit) ...@@ -2903,19 +2937,27 @@ ifaceas1(Type *dst, Type *src, int explicit)
if(isinter(dst)) { if(isinter(dst)) {
if(isinter(src)) { if(isinter(src)) {
if(isnilinter(dst)) {
if(isnilinter(src))
return E2Esame;
return I2E;
}
if(eqtype(dst, src)) if(eqtype(dst, src))
return I2Isame; return I2Isame;
if(!isnilinter(dst)) ifacecheck(dst, src, lineno, explicit);
ifacecheck(dst, src, lineno, explicit); if(isnilinter(src))
return E2I;
return I2I; return I2I;
} }
if(isnilinter(dst)) if(isnilinter(dst))
return T2I; return T2E;
ifacecheck(dst, src, lineno, explicit); ifacecheck(dst, src, lineno, explicit);
return T2I; return T2I;
} }
if(isinter(src)) { if(isinter(src)) {
ifacecheck(dst, src, lineno, explicit); ifacecheck(dst, src, lineno, explicit);
if(isnilinter(src))
return E2T;
return I2T; return I2T;
} }
return Inone; return Inone;
...@@ -2930,7 +2972,7 @@ ifaceas(Type *dst, Type *src, int explicit) ...@@ -2930,7 +2972,7 @@ ifaceas(Type *dst, Type *src, int explicit)
int et; int et;
et = ifaceas1(dst, src, explicit); et = ifaceas1(dst, src, explicit);
if(et == I2Isame) if(et == I2Isame || et == E2Esame)
et = Inone; et = Inone;
return et; return et;
} }
...@@ -2943,6 +2985,15 @@ ifacename[] = ...@@ -2943,6 +2985,15 @@ ifacename[] =
[I2I] = "ifaceI2I", [I2I] = "ifaceI2I",
[I2I2] = "ifaceI2I2", [I2I2] = "ifaceI2I2",
[I2Isame] = "ifaceI2Isame", [I2Isame] = "ifaceI2Isame",
[E2T] = "ifaceE2T",
[E2T2] = "ifaceE2T2",
[E2I] = "ifaceE2I",
[E2I2] = "ifaceE2I2",
[I2E] = "ifaceI2E",
[I2E2] = "ifaceI2E2",
[T2I] = "ifaceT2I",
[T2E] = "ifaceT2E",
[E2Esame] = "ifaceE2Esame",
}; };
Node* Node*
...@@ -2982,19 +3033,21 @@ ifaceop(Type *tl, Node *n, int op) ...@@ -2982,19 +3033,21 @@ ifaceop(Type *tl, Node *n, int op)
on = syslook("ifaceT2I", 1); on = syslook("ifaceT2I", 1);
argtype(on, tr); argtype(on, tr);
argtype(on, tl); argtype(on, tl);
break; break;
case I2T: case I2T:
case I2T2: case I2T2:
case I2I: case I2I:
case I2I2: case I2I2:
case E2T:
case E2T2:
case E2I:
case E2I2:
// iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]); // iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]);
a = n; // interface a = n; // interface
r = a; r = a;
s = signame(tl); // sigi s = signame(tl); // sigi or sigt
if(s == S) if(s == S)
fatal("ifaceop: signame %d", op); fatal("ifaceop: signame %d", op);
a = s->oname; a = s->oname;
...@@ -3004,7 +3057,34 @@ ifaceop(Type *tl, Node *n, int op) ...@@ -3004,7 +3057,34 @@ ifaceop(Type *tl, Node *n, int op)
on = syslook(ifacename[op], 1); on = syslook(ifacename[op], 1);
argtype(on, tr); argtype(on, tr);
argtype(on, tl); 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; break;
case OEQ: case OEQ:
...@@ -3016,7 +3096,12 @@ ifaceop(Type *tl, Node *n, int op) ...@@ -3016,7 +3096,12 @@ ifaceop(Type *tl, Node *n, int op)
a = n->left; // i1 a = n->left; // i1
r = list(a, r); 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->right->type);
argtype(on, n->left->type); argtype(on, n->left->type);
......
This diff is collapsed.
...@@ -363,7 +363,7 @@ static void ...@@ -363,7 +363,7 @@ static void
interprint(uint32 s, Iface *a) interprint(uint32 s, Iface *a)
{ {
USED(s); USED(s);
sys·printinter(*a); sys·printiface(*a);
} }
static uint32 static uint32
...@@ -373,6 +373,27 @@ interequal(uint32 s, Iface *a, Iface *b) ...@@ -373,6 +373,27 @@ interequal(uint32 s, Iface *a, Iface *b)
return ifaceeq(*a, *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 uint64
nohash(uint32 s, void *a) nohash(uint32 s, void *a)
{ {
...@@ -416,6 +437,7 @@ algarray[] = ...@@ -416,6 +437,7 @@ algarray[] =
[ANOEQ] { nohash, noequal, memprint, memcopy }, [ANOEQ] { nohash, noequal, memprint, memcopy },
[ASTRING] { strhash, strequal, strprint, memcopy }, [ASTRING] { strhash, strequal, strprint, memcopy },
[AINTER] { interhash, interequal, interprint, memcopy }, [AINTER] { interhash, interequal, interprint, memcopy },
[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy },
[AFAKE] { nohash, noequal, noprint, nocopy }, [AFAKE] { nohash, noequal, noprint, nocopy },
}; };
......
...@@ -57,6 +57,8 @@ typedef struct SigTab SigTab; ...@@ -57,6 +57,8 @@ typedef struct SigTab SigTab;
typedef struct MCache MCache; typedef struct MCache MCache;
typedef struct Iface Iface; typedef struct Iface Iface;
typedef struct Itype Itype; typedef struct Itype Itype;
typedef struct Eface Eface;
typedef struct Sigt Sigt;
typedef struct Defer Defer; typedef struct Defer Defer;
/* /*
...@@ -118,6 +120,11 @@ struct Iface ...@@ -118,6 +120,11 @@ struct Iface
Itype* type; Itype* type;
void* data; void* data;
}; };
struct Eface
{
Sigt* type;
void* data;
};
struct Array struct Array
{ // must not move anything { // must not move anything
...@@ -238,6 +245,7 @@ enum ...@@ -238,6 +245,7 @@ enum
ANOEQ, ANOEQ,
ASTRING, ASTRING,
AINTER, AINTER,
ANILINTER,
AFAKE, AFAKE,
Amax Amax
}; };
...@@ -323,7 +331,9 @@ void stackfree(void*); ...@@ -323,7 +331,9 @@ void stackfree(void*);
MCache* allocmcache(void); MCache* allocmcache(void);
void mallocinit(void); void mallocinit(void);
bool ifaceeq(Iface, Iface); bool ifaceeq(Iface, Iface);
bool efaceeq(Eface, Eface);
uint64 ifacehash(Iface); uint64 ifacehash(Iface);
uint64 efacehash(Eface);
uint64 nohash(uint32, void*); uint64 nohash(uint32, void*);
uint32 noequal(uint32, void*, void*); uint32 noequal(uint32, void*, void*);
void* malloc(uintptr size); void* malloc(uintptr size);
...@@ -396,7 +406,8 @@ void notewakeup(Note*); ...@@ -396,7 +406,8 @@ void notewakeup(Note*);
#define sys_printfloat sys·printfloat #define sys_printfloat sys·printfloat
#define sys_printhex sys·printhex #define sys_printhex sys·printhex
#define sys_printint sys·printint #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_printpc sys·printpc
#define sys_printpointer sys·printpointer #define sys_printpointer sys·printpointer
#define sys_printstring sys·printstring #define sys_printstring sys·printstring
...@@ -420,7 +431,8 @@ void* sys_getcallerpc(void*); ...@@ -420,7 +431,8 @@ void* sys_getcallerpc(void*);
void sys_printbool(bool); void sys_printbool(bool);
void sys_printfloat(float64); void sys_printfloat(float64);
void sys_printint(int64); void sys_printint(int64);
void sys_printinter(Iface); void sys_printiface(Iface);
void sys_printeface(Eface);
void sys_printstring(String); void sys_printstring(String);
void sys_printpc(void*); void sys_printpc(void*);
void sys_printpointer(void*); void sys_printpointer(void*);
......
...@@ -225,7 +225,7 @@ fixedbugs/bug103.go:8: illegal types for operand: AS ...@@ -225,7 +225,7 @@ fixedbugs/bug103.go:8: illegal types for operand: AS
int int
=========== fixedbugs/bug113.go =========== fixedbugs/bug113.go
main.I is int, not int32 interface is int, not int32
throw: interface conversion throw: interface conversion
panic PC=xxx panic PC=xxx
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment