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:
parent
98178b345a
commit
6f6a9445c9
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user