]> Cypherpunks repositories - gostls13.git/commitdiff
runtime, cmd/gc: Get rid of vararg channel calls.
authorKeith Randall <khr@golang.org>
Fri, 17 Jan 2014 22:48:45 +0000 (14:48 -0800)
committerKeith Randall <khr@golang.org>
Fri, 17 Jan 2014 22:48:45 +0000 (14:48 -0800)
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

src/cmd/gc/builtin.c
src/cmd/gc/runtime.go
src/cmd/gc/select.c
src/cmd/gc/walk.c
src/pkg/runtime/chan.c

index 1b0297d7ca53440e34c2b62b58dbe754cb514324..4955231c20231a18e609b7078069754a0491bd46 100644 (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"
index 852a545a91f35487bc755b9159bd5e922427b069..c65365f55ae05e9763df18f437679dcaa42915f3 100644 (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
 
index cd3de8c7beb7154d0ec6db1fad96482c63cd0265..35da0557b61698d58b21f79f14d2234aa801b737 100644 (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:
index e1a909ce69337abfb0dace9de1a082c28e30e9d7..eb5a3f1b6b9f7e633787447821b5be1a751c7c6e 100644 (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:
index cee35c3efd9470d0e5591e0bd9daeec5bec2d8ff..d90dc78e16152c7d6db1ff06c0e1a5f9e50f4414 100644 (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) {