Commit 6f6a9445 authored by Keith Randall's avatar Keith Randall

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
parent 98178b34
...@@ -77,11 +77,11 @@ char *runtimeimport = ...@@ -77,11 +77,11 @@ char *runtimeimport =
"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any)\n" "func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any)\n"
"func @\"\".mapiternext (@\"\".hiter·1 *any)\n" "func @\"\".mapiternext (@\"\".hiter·1 *any)\n"
"func @\"\".makechan (@\"\".chanType·2 *byte, @\"\".hint·3 int64) (@\"\".hchan·1 chan 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 @\"\".chanrecv1 (@\"\".chanType·1 *byte, @\"\".hchan·2 <-chan any, @\"\".elem·3 *any)\n"
"func @\"\".chanrecv2 (@\"\".chanType·3 *byte, @\"\".hchan·4 <-chan any) (@\"\".elem·1 any, @\"\".received·2 bool)\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 @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n"
"func @\"\".closechan (@\"\".hchan·1 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 @\"\".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 @\"\".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" "func @\"\".newselect (@\"\".size·2 int32) (@\"\".sel·1 *byte)\n"
......
...@@ -101,12 +101,12 @@ func mapiternext(hiter *any) ...@@ -101,12 +101,12 @@ func mapiternext(hiter *any)
// *byte is really *runtime.Type // *byte is really *runtime.Type
func makechan(chanType *byte, hint int64) (hchan chan any) func makechan(chanType *byte, hint int64) (hchan chan any)
func chanrecv1(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, received bool) func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
func chansend1(chanType *byte, hchan chan<- any, elem any) func chansend1(chanType *byte, hchan chan<- any, elem *any)
func closechan(hchan 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 selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool
......
...@@ -252,8 +252,20 @@ walkselect(Node *sel) ...@@ -252,8 +252,20 @@ walkselect(Node *sel)
case OSEND: case OSEND:
// if c != nil && selectnbsend(c, v) { body } else { default body } // if c != nil && selectnbsend(c, v) { body } else { default body }
ch = cheapexpr(n->left, &r->ninit); 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), 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; break;
case OSELRECV: case OSELRECV:
......
...@@ -163,7 +163,6 @@ walkstmt(Node **np) ...@@ -163,7 +163,6 @@ walkstmt(Node **np)
case OCALLFUNC: case OCALLFUNC:
case ODELETE: case ODELETE:
case OSEND: case OSEND:
case ORECV:
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
case OPANIC: case OPANIC:
...@@ -179,6 +178,21 @@ walkstmt(Node **np) ...@@ -179,6 +178,21 @@ walkstmt(Node **np)
n->op = OEMPTY; // don't leave plain values as statements. n->op = OEMPTY; // don't leave plain values as statements.
break; 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 OBREAK:
case ODCL: case ODCL:
case OCONTINUE: case OCONTINUE:
...@@ -593,6 +607,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -593,6 +607,7 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OAS2: case OAS2:
as2:
*init = concat(*init, n->ninit); *init = concat(*init, n->ninit);
n->ninit = nil; n->ninit = nil;
walkexprlistsafe(n->list, init); walkexprlistsafe(n->list, init);
...@@ -603,7 +618,6 @@ walkexpr(Node **np, NodeList **init) ...@@ -603,7 +618,6 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OAS2FUNC: case OAS2FUNC:
as2func:
// a,b,... = fn() // a,b,... = fn()
*init = concat(*init, n->ninit); *init = concat(*init, n->ninit);
n->ninit = nil; n->ninit = nil;
...@@ -645,11 +659,13 @@ walkexpr(Node **np, NodeList **init) ...@@ -645,11 +659,13 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n; r = n->rlist->n;
walkexprlistsafe(n->list, init); walkexprlistsafe(n->list, init);
walkexpr(&r->left, init); walkexpr(&r->left, init);
var = temp(r->left->type->type);
n1 = nod(OADDR, var, N);
fn = chanfn("chanrecv2", 2, r->left->type); fn = chanfn("chanrecv2", 2, r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left); r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1);
n->rlist->n = r; n->op = OAS2;
n->op = OAS2FUNC; n->rlist = concat(list1(var), list1(r));
goto as2func; goto as2;
case OAS2MAPR: case OAS2MAPR:
// a,b = m[i]; // a,b = m[i];
...@@ -1149,8 +1165,12 @@ walkexpr(Node **np, NodeList **init) ...@@ -1149,8 +1165,12 @@ walkexpr(Node **np, NodeList **init)
case ORECV: case ORECV:
walkexpr(&n->left, init); walkexpr(&n->left, init);
walkexpr(&n->right, init); var = temp(n->left->type->type);
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left); 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; goto ret;
case OSLICE: case OSLICE:
...@@ -1427,7 +1447,19 @@ walkexpr(Node **np, NodeList **init) ...@@ -1427,7 +1447,19 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OSEND: 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; goto ret;
case OCLOSURE: case OCLOSURE:
......
...@@ -430,35 +430,31 @@ closed: ...@@ -430,35 +430,31 @@ closed:
runtime·blockevent(mysg.releasetime - t0, 2); runtime·blockevent(mysg.releasetime - t0, 2);
} }
// chansend1(hchan *chan any, elem any); // chansend1(hchan *chan any, elem *any);
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
void 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 #pragma textflag NOSPLIT
void 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 #pragma textflag NOSPLIT
void void
runtime·chanrecv2(ChanType *t, Hchan* c, ...) runtime·chanrecv2(ChanType *t, Hchan* c, byte *v, bool received)
{ {
byte *ae, *ap; runtime·chanrecv(t, c, v, nil, &received);
ae = (byte*)(&c+1);
ap = ae + t->elem->size;
runtime·chanrecv(t, c, ae, nil, ap);
} }
// func selectnbsend(c chan any, elem any) bool // func selectnbsend(c chan any, elem *any) bool
// //
// compiler implements // compiler implements
// //
...@@ -479,13 +475,9 @@ runtime·chanrecv2(ChanType *t, Hchan* c, ...) ...@@ -479,13 +475,9 @@ runtime·chanrecv2(ChanType *t, Hchan* c, ...)
// //
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
void void
runtime·selectnbsend(ChanType *t, Hchan *c, ...) runtime·selectnbsend(ChanType *t, Hchan *c, byte *val, bool pres)
{ {
byte *ae, *ap; runtime·chansend(t, c, val, &pres, runtime·getcallerpc(&t));
ae = (byte*)(&c + 1);
ap = ae + ROUND(t->elem->size, Structrnd);
runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
} }
// func selectnbrecv(elem *any, c chan any) bool // 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 ...@@ -585,23 +577,19 @@ reflect·chanrecv(ChanType *t, Hchan *c, bool nb, byte *val, bool selected, bool
runtime·chanrecv(t, c, val, sp, &received); runtime·chanrecv(t, c, val, sp, &received);
} }
static void newselect(int32, Select**); static Select* newselect(int32);
// newselect(size uint32) (sel *byte); // newselect(size uint32) (sel *byte);
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
void void
runtime·newselect(int32 size, ...) runtime·newselect(int32 size, byte *sel)
{ {
int32 o; sel = (byte*)newselect(size);
Select **selp; FLUSH(&sel);
o = ROUND(sizeof(size), Structrnd);
selp = (Select**)((byte*)&size + o);
newselect(size, selp);
} }
static void static Select*
newselect(int32 size, Select **selp) newselect(int32 size)
{ {
int32 n; int32 n;
Select *sel; Select *sel;
...@@ -623,10 +611,10 @@ newselect(int32 size, Select **selp) ...@@ -623,10 +611,10 @@ newselect(int32 size, Select **selp)
sel->ncase = 0; sel->ncase = 0;
sel->lockorder = (void*)(sel->scase + size); sel->lockorder = (void*)(sel->scase + size);
sel->pollorder = (void*)(sel->lockorder + size); sel->pollorder = (void*)(sel->lockorder + size);
*selp = sel;
if(debug) if(debug)
runtime·printf("newselect s=%p size=%d\n", sel, size); runtime·printf("newselect s=%p size=%d\n", sel, size);
return sel;
} }
// cut in half to give stack a chance to split // cut in half to give stack a chance to split
...@@ -1158,7 +1146,7 @@ reflect·rselect(Slice cases, intgo chosen, bool recvOK) ...@@ -1158,7 +1146,7 @@ reflect·rselect(Slice cases, intgo chosen, bool recvOK)
rcase = (runtimeSelect*)cases.array; rcase = (runtimeSelect*)cases.array;
newselect(cases.len, &sel); sel = newselect(cases.len);
for(i=0; i<cases.len; i++) { for(i=0; i<cases.len; i++) {
rc = &rcase[i]; rc = &rcase[i];
switch(rc->dir) { switch(rc->dir) {
......
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