1
0
mirror of https://github.com/golang/go synced 2024-11-12 09:50:21 -07:00

runtime, cmd/gc: Get rid of vararg channel calls.

Vararg C calls present a problem for the GC because the
argument types are not derivable from the signature.  Remove
them by passing pointers to channel elements instead of the
channel elements directly.

R=golang-codereviews, gobot, rsc, dvyukov
CC=golang-codereviews
https://golang.org/cl/53430043
This commit is contained in:
Keith Randall 2014-01-17 14:48:45 -08:00
parent 98178b345a
commit 6f6a9445c9
5 changed files with 82 additions and 50 deletions

View File

@ -77,11 +77,11 @@ char *runtimeimport =
"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any)\n"
"func @\"\".mapiternext (@\"\".hiter·1 *any)\n"
"func @\"\".makechan (@\"\".chanType·2 *byte, @\"\".hint·3 int64) (@\"\".hchan·1 chan any)\n"
"func @\"\".chanrecv1 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any) (@\"\".elem·1 any)\n"
"func @\"\".chanrecv2 (@\"\".chanType·3 *byte, @\"\".hchan·4 <-chan any) (@\"\".elem·1 any, @\"\".received·2 bool)\n"
"func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 any)\n"
"func @\"\".chanrecv1 (@\"\".chanType·1 *byte, @\"\".hchan·2 <-chan any, @\"\".elem·3 *any)\n"
"func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n"
"func @\"\".closechan (@\"\".hchan·1 any)\n"
"func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 any) (? bool)\n"
"func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
"func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n"
"func @\"\".newselect (@\"\".size·2 int32) (@\"\".sel·1 *byte)\n"

View File

@ -101,12 +101,12 @@ func mapiternext(hiter *any)
// *byte is really *runtime.Type
func makechan(chanType *byte, hint int64) (hchan chan any)
func chanrecv1(chanType *byte, hchan <-chan any) (elem any)
func chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool)
func chansend1(chanType *byte, hchan chan<- any, elem any)
func chanrecv1(chanType *byte, hchan <-chan any, elem *any)
func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
func chansend1(chanType *byte, hchan chan<- any, elem *any)
func closechan(hchan any)
func selectnbsend(chanType *byte, hchan chan<- any, elem any) bool
func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool

View File

@ -252,8 +252,20 @@ walkselect(Node *sel)
case OSEND:
// if c != nil && selectnbsend(c, v) { body } else { default body }
ch = cheapexpr(n->left, &r->ninit);
a = n->right;
a = assignconv(a, ch->type->type, "select chan send");
walkexpr(&a, &r->ninit);
if(islvalue(a)) {
a = nod(OADDR, a, N);
} else {
var = temp(a->type);
tmp = nod(OAS, var, a);
typecheck(&tmp, Etop);
r->ninit = list(r->ninit, tmp);
a = nod(OADDR, var, N);
}
r->ntest = mkcall1(chanfn("selectnbsend", 2, ch->type),
types[TBOOL], &r->ninit, typename(ch->type), ch, n->right);
types[TBOOL], &r->ninit, typename(ch->type), ch, a);
break;
case OSELRECV:

View File

@ -163,7 +163,6 @@ walkstmt(Node **np)
case OCALLFUNC:
case ODELETE:
case OSEND:
case ORECV:
case OPRINT:
case OPRINTN:
case OPANIC:
@ -179,6 +178,21 @@ walkstmt(Node **np)
n->op = OEMPTY; // don't leave plain values as statements.
break;
case ORECV:
// special case for a receive where we throw away
// the value received.
if(n->typecheck == 0)
fatal("missing typecheck: %+N", n);
init = n->ninit;
n->ninit = nil;
walkexpr(&n->left, &init);
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil());
walkexpr(&n, &init);
addinit(&n, init);
break;
case OBREAK:
case ODCL:
case OCONTINUE:
@ -593,6 +607,7 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OAS2:
as2:
*init = concat(*init, n->ninit);
n->ninit = nil;
walkexprlistsafe(n->list, init);
@ -603,7 +618,6 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OAS2FUNC:
as2func:
// a,b,... = fn()
*init = concat(*init, n->ninit);
n->ninit = nil;
@ -645,11 +659,13 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
var = temp(r->left->type->type);
n1 = nod(OADDR, var, N);
fn = chanfn("chanrecv2", 2, r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left);
n->rlist->n = r;
n->op = OAS2FUNC;
goto as2func;
r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1);
n->op = OAS2;
n->rlist = concat(list1(var), list1(r));
goto as2;
case OAS2MAPR:
// a,b = m[i];
@ -1149,8 +1165,12 @@ walkexpr(Node **np, NodeList **init)
case ORECV:
walkexpr(&n->left, init);
walkexpr(&n->right, init);
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left);
var = temp(n->left->type->type);
n1 = nod(OADDR, var, N);
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
walkexpr(&n, init);
*init = list(*init, n);
n = var;
goto ret;
case OSLICE:
@ -1427,7 +1447,19 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OSEND:
n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right);
n1 = n->right;
n1 = assignconv(n1, n->left->type->type, "chan send");
walkexpr(&n1, init);
if(islvalue(n1)) {
n1 = nod(OADDR, n1, N);
} else {
var = temp(n1->type);
n1 = nod(OAS, var, n1);
typecheck(&n1, Etop);
*init = list(*init, n1);
n1 = nod(OADDR, var, N);
}
n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
goto ret;
case OCLOSURE:

View File

@ -430,35 +430,31 @@ closed:
runtime·blockevent(mysg.releasetime - t0, 2);
}
// chansend1(hchan *chan any, elem any);
// chansend1(hchan *chan any, elem *any);
#pragma textflag NOSPLIT
void
runtime·chansend1(ChanType *t, Hchan* c, ...)
runtime·chansend1(ChanType *t, Hchan* c, byte *v)
{
runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
runtime·chansend(t, c, v, nil, runtime·getcallerpc(&t));
}
// chanrecv1(hchan *chan any) (elem any);
// chanrecv1(hchan *chan any, elem *any);
#pragma textflag NOSPLIT
void
runtime·chanrecv1(ChanType *t, Hchan* c, ...)
runtime·chanrecv1(ChanType *t, Hchan* c, byte *v)
{
runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil);
runtime·chanrecv(t, c, v, nil, nil);
}
// chanrecv2(hchan *chan any) (elem any, received bool);
// chanrecv2(hchan *chan any, elem *any) (received bool);
#pragma textflag NOSPLIT
void
runtime·chanrecv2(ChanType *t, Hchan* c, ...)
runtime·chanrecv2(ChanType *t, Hchan* c, byte *v, bool received)
{
byte *ae, *ap;
ae = (byte*)(&c+1);
ap = ae + t->elem->size;
runtime·chanrecv(t, c, ae, nil, ap);
runtime·chanrecv(t, c, v, nil, &received);
}
// func selectnbsend(c chan any, elem any) bool
// func selectnbsend(c chan any, elem *any) bool
//
// compiler implements
//
@ -479,13 +475,9 @@ runtime·chanrecv2(ChanType *t, Hchan* c, ...)
//
#pragma textflag NOSPLIT
void
runtime·selectnbsend(ChanType *t, Hchan *c, ...)
runtime·selectnbsend(ChanType *t, Hchan *c, byte *val, bool pres)
{
byte *ae, *ap;
ae = (byte*)(&c + 1);
ap = ae + ROUND(t->elem->size, Structrnd);
runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
runtime·chansend(t, c, val, &pres, runtime·getcallerpc(&t));
}
// func selectnbrecv(elem *any, c chan any) bool
@ -585,23 +577,19 @@ reflect·chanrecv(ChanType *t, Hchan *c, bool nb, byte *val, bool selected, bool
runtime·chanrecv(t, c, val, sp, &received);
}
static void newselect(int32, Select**);
static Select* newselect(int32);
// newselect(size uint32) (sel *byte);
#pragma textflag NOSPLIT
void
runtime·newselect(int32 size, ...)
runtime·newselect(int32 size, byte *sel)
{
int32 o;
Select **selp;
o = ROUND(sizeof(size), Structrnd);
selp = (Select**)((byte*)&size + o);
newselect(size, selp);
sel = (byte*)newselect(size);
FLUSH(&sel);
}
static void
newselect(int32 size, Select **selp)
static Select*
newselect(int32 size)
{
int32 n;
Select *sel;
@ -623,10 +611,10 @@ newselect(int32 size, Select **selp)
sel->ncase = 0;
sel->lockorder = (void*)(sel->scase + size);
sel->pollorder = (void*)(sel->lockorder + size);
*selp = sel;
if(debug)
runtime·printf("newselect s=%p size=%d\n", sel, size);
return sel;
}
// cut in half to give stack a chance to split
@ -1158,7 +1146,7 @@ reflect·rselect(Slice cases, intgo chosen, bool recvOK)
rcase = (runtimeSelect*)cases.array;
newselect(cases.len, &sel);
sel = newselect(cases.len);
for(i=0; i<cases.len; i++) {
rc = &rcase[i];
switch(rc->dir) {