Commit 8bf34e33 authored by Russ Cox's avatar Russ Cox

gc, runtime: replace closed(c) with x, ok := <-c

R=ken2, ken3
CC=golang-dev
https://golang.org/cl/4259064
parent 9f2cb86f
......@@ -66,15 +66,17 @@ char *runtimeimport =
"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
"func \"\".makechan (elem *uint8, hint int64) chan any\n"
"func \"\".chanrecv1 (hchan <-chan any) any\n"
"func \"\".chanrecv3 (hchan <-chan any) (elem any, closed bool)\n"
"func \"\".chanrecv2 (hchan <-chan any) (elem any, received bool)\n"
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
"func \"\".closechan (hchan any)\n"
"func \"\".closedchan (hchan any) bool\n"
"func \"\".selectnbsend (hchan chan<- any, elem any) bool\n"
"func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n"
"func \"\".selectnbrecv2 (elem *any, received *bool, hchan <-chan any) bool\n"
"func \"\".newselect (size int) *uint8\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) bool\n"
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
"func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n"
"func \"\".selectdefault (sel *uint8) bool\n"
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
......
......@@ -356,12 +356,11 @@ enum
OARRAY,
OARRAYBYTESTR, OARRAYRUNESTR,
OSTRARRAYBYTE, OSTRARRAYRUNE,
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECVCLOSED, OAS2MAPR, OAS2DOTTYPE, OASOP,
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
OBAD,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OCAP,
OCLOSE,
OCLOSED,
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
......@@ -389,6 +388,7 @@ enum
ORECV,
ORUNESTR,
OSELRECV,
OSELRECV2,
OIOTA,
OREAL, OIMAG, OCOMPLEX,
......
......@@ -461,23 +461,32 @@ case:
}
break;
}
| LCASE expr '=' expr ':'
| LCASE expr_or_type_list '=' expr ':'
{
Node *n;
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
$$->list = list1(nod(OAS, $2, $4));
if($2->next == nil)
n = nod(OAS, $2->n, $4);
else {
n = nod(OAS2, N, N);
n->list = $2;
n->rlist = list1($4);
}
$$->list = list1(n);
}
| LCASE name LCOLAS expr ':'
| LCASE expr_or_type_list LCOLAS expr ':'
{
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
$$->list = list1(colas(list1($2), list1($4)));
$$->list = list1(colas($2, list1($4)));
}
| LDEFAULT ':'
{
......
......@@ -1555,7 +1555,6 @@ static struct
"append", LNAME, Txxx, OAPPEND,
"cap", LNAME, Txxx, OCAP,
"close", LNAME, Txxx, OCLOSE,
"closed", LNAME, Txxx, OCLOSED,
"complex", LNAME, Txxx, OCOMPLEX,
"copy", LNAME, Txxx, OCOPY,
"imag", LNAME, Txxx, OIMAG,
......
......@@ -52,7 +52,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case OARRAYBYTESTR:
case OCAP:
case OCLOSE:
case OCLOSED:
case OCOPY:
case OLEN:
case OMAKE:
......@@ -405,7 +404,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case OAPPEND:
case OCAP:
case OCLOSE:
case OCLOSED:
case OLEN:
case OCOPY:
case OMAKE:
......
......@@ -203,8 +203,8 @@ walkrange(Node *n)
hb = nod(OXXX, N, N);
tempname(hb, types[TBOOL]);
n->ntest = nod(ONOT, hb, N);
a = nod(OAS2RECVCLOSED, N, N);
n->ntest = hb;
a = nod(OAS2RECV, N, N);
a->typecheck = 1;
a->list = list(list1(hv1), hb);
a->rlist = list1(nod(ORECV, ha, N));
......
......@@ -92,17 +92,19 @@ func mapiter2(hiter *any) (key any, val any)
// *byte is really *runtime.Type
func makechan(elem *byte, hint int64) (hchan chan any)
func chanrecv1(hchan <-chan any) (elem any)
func chanrecv3(hchan <-chan any) (elem any, closed bool)
func chanrecv2(hchan <-chan any) (elem any, received bool)
func chansend1(hchan chan<- any, elem any)
func closechan(hchan any)
func closedchan(hchan any) bool
func selectnbsend(hchan chan<- any, elem any) bool
func selectnbrecv(elem *any, hchan <-chan any) bool
func selectnbrecv2(elem *any, received *bool, hchan <-chan any) bool
func newselect(size int) (sel *byte)
func selectsend(sel *byte, hchan chan<- any, elem any) (selected bool)
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
func selectdefault(sel *byte) (selected bool)
func selectgo(sel *byte)
func block()
......
......@@ -58,6 +58,18 @@ typecheckselect(Node *sel)
n->op = OSELRECV;
break;
case OAS2RECV:
// convert x, ok = <-c into OSELRECV(x, <-c) with ntest=ok
if(n->right->op != ORECV) {
yyerror("select assignment must have receive on right hand side");
break;
}
n->op = OSELRECV2;
n->left = n->list->n;
n->ntest = n->list->next->n;
n->right = n->rlist->n;
break;
case ORECV:
// convert <-c into OSELRECV(N, <-c)
n = nod(OSELRECV, N, n);
......@@ -122,6 +134,18 @@ walkselect(Node *sel)
typecheck(&n, Etop);
}
break;
case OSELRECV2:
r = n->right;
ch = cheapexpr(r->left, &l);
r->left = ch;
a = nod(OAS2, N, N);
a->list = n->list;
a->rlist = n->rlist;
n = a;
typecheck(&n, Etop);
break;
}
// if ch == nil { block() }; n;
......@@ -146,6 +170,7 @@ walkselect(Node *sel)
continue;
switch(n->op) {
case OSELRECV:
case OSELRECV2:
ch = n->right->left;
// If we can use the address of the target without
......@@ -154,6 +179,28 @@ walkselect(Node *sel)
// Also introduce a temporary for := variables that escape,
// so that we can delay the heap allocation until the case
// is selected.
if(n->op == OSELRECV2) {
if(n->ntest == N || isblank(n->ntest))
n->ntest = nodnil();
else if(n->ntest->op == ONAME &&
(!n->colas || (n->ntest->class&PHEAP) == 0) &&
convertop(types[TBOOL], n->ntest->type, nil) == OCONVNOP) {
n->ntest = nod(OADDR, n->ntest, N);
n->ntest->etype = 1; // pointer does not escape
typecheck(&n->ntest, Erv);
} else {
tmp = nod(OXXX, N, N);
tempname(tmp, types[TBOOL]);
a = nod(OADDR, tmp, N);
a->etype = 1; // pointer does not escape
typecheck(&a, Erv);
r = nod(OAS, n->ntest, tmp);
typecheck(&r, Etop);
cas->nbody = concat(list1(r), cas->nbody);
n->ntest = a;
}
}
if(n->left == N || isblank(n->left))
n->left = nodnil();
else if(n->left->op == ONAME &&
......@@ -171,10 +218,12 @@ walkselect(Node *sel)
r = nod(OAS, n->left, tmp);
typecheck(&r, Etop);
cas->nbody = concat(list1(r), cas->nbody);
cas->nbody = concat(n->ninit, cas->nbody);
n->ninit = nil;
n->left = a;
}
cas->nbody = concat(n->ninit, cas->nbody);
n->ninit = nil;
break;
}
}
......@@ -212,6 +261,16 @@ walkselect(Node *sel)
mkcall1(chanfn("selectnbrecv", 2, ch->type),
types[TBOOL], &r->ninit, n->left, ch));
break;
case OSELRECV2:
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
r = nod(OIF, N, N);
r->ninit = cas->ninit;
ch = cheapexpr(n->right->left, &r->ninit);
r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
mkcall1(chanfn("selectnbrecv2", 2, ch->type),
types[TBOOL], &r->ninit, n->left, n->ntest, ch));
break;
}
typecheck(&r->ntest, Erv);
r->nbody = cas->nbody;
......@@ -254,11 +313,18 @@ walkselect(Node *sel)
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
&init, var, n->left, n->right);
break;
case OSELRECV:
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
&init, var, n->right->left, n->left);
break;
case OSELRECV2:
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
r->ntest = mkcall1(chanfn("selectrecv2", 2, n->right->left->type), types[TBOOL],
&init, var, n->right->left, n->left, n->ntest);
break;
}
}
r->nbody = concat(r->nbody, cas->nbody);
......
......@@ -94,7 +94,7 @@ init1(Node *n, NodeList **out)
case OAS2FUNC:
case OAS2MAPR:
case OAS2DOTTYPE:
case OAS2RECVCLOSED:
case OAS2RECV:
if(n->defn->initorder)
break;
n->defn->initorder = 1;
......
......@@ -834,7 +834,6 @@ goopnames[] =
[OCALL] = "function call",
[OCAP] = "cap",
[OCASE] = "case",
[OCLOSED] = "closed",
[OCLOSE] = "close",
[OCOMPLEX] = "complex",
[OCOM] = "^",
......@@ -1669,6 +1668,9 @@ isselect(Node *n)
if(s == n->sym)
return 1;
s = pkglookup("selectrecv", runtimepkg);
if(s == n->sym)
return 1;
s = pkglookup("selectrecv2", runtimepkg);
if(s == n->sym)
return 1;
s = pkglookup("selectdefault", runtimepkg);
......
......@@ -921,7 +921,6 @@ reswitch:
n->type = t;
goto ret;
case OCLOSED:
case OCLOSE:
if(onearg(n, "%#O", n->op) < 0)
goto error;
......@@ -934,10 +933,6 @@ reswitch:
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error;
}
if(n->op == OCLOSED) {
n->type = types[TBOOL];
ok |= Erv;
} else
ok |= Etop;
goto ret;
......@@ -2377,8 +2372,9 @@ typecheckas2(Node *n)
n->op = OAS2MAPR;
goto common;
case ORECV:
yyerror("cannot use multiple-value assignment for non-blocking receive; use select");
goto out;
n->op = OAS2RECV;
n->right = n->rlist->n;
goto common;
case ODOTTYPE:
n->op = OAS2DOTTYPE;
r->op = ODOTTYPE2;
......
......@@ -403,12 +403,11 @@ walkstmt(Node **np)
case OAS:
case OAS2:
case OAS2DOTTYPE:
case OAS2RECVCLOSED:
case OAS2RECV:
case OAS2FUNC:
case OAS2MAPW:
case OAS2MAPR:
case OCLOSE:
case OCLOSED:
case OCOPY:
case OCALLMETH:
case OCALLINTER:
......@@ -822,14 +821,13 @@ walkexpr(Node **np, NodeList **init)
n = liststmt(concat(concat(list1(r), ll), lpost));
goto ret;
case OAS2RECVCLOSED:
// a = <-c; b = closed(c) but atomic
case OAS2RECV:
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
fn = chanfn("chanrecv3", 2, r->left->type);
fn = chanfn("chanrecv2", 2, r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, r->left);
n->rlist->n = r;
n->op = OAS2FUNC;
......@@ -1309,13 +1307,6 @@ walkexpr(Node **np, NodeList **init)
n = mkcall1(fn, T, init, n->left);
goto ret;
case OCLOSED:
// cannot use chanfn - closechan takes any, not chan any
fn = syslook("closedchan", 1);
argtype(fn, n->left->type);
n = mkcall1(fn, n->type, init, n->left);
goto ret;
case OMAKECHAN:
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
typename(n->type->type),
......
This diff is collapsed.
......@@ -70,22 +70,18 @@ func makechan(typ *byte, size uint32) (ch *byte) {
ch = (byte*)runtime·makechan_c(t->elem, size);
}
func chansend(ch *byte, val *byte, pres *bool) {
runtime·chansend((Hchan*)ch, val, pres);
func chansend(ch *byte, val *byte, selected *bool) {
runtime·chansend((Hchan*)ch, val, selected);
}
func chanrecv(ch *byte, val *byte, pres *bool) {
runtime·chanrecv((Hchan*)ch, val, pres, nil);
func chanrecv(ch *byte, val *byte, selected *bool, received *bool) {
runtime·chanrecv((Hchan*)ch, val, selected, received);
}
func chanclose(ch *byte) {
runtime·chanclose((Hchan*)ch);
}
func chanclosed(ch *byte) (r bool) {
r = runtime·chanclosed((Hchan*)ch);
}
func chanlen(ch *byte) (r int32) {
r = runtime·chanlen((Hchan*)ch);
}
......
......@@ -585,7 +585,6 @@ Hchan* runtime·makechan_c(Type*, int64);
void runtime·chansend(Hchan*, void*, bool*);
void runtime·chanrecv(Hchan*, void*, bool*, bool*);
void runtime·chanclose(Hchan*);
bool runtime·chanclosed(Hchan*);
int32 runtime·chanlen(Hchan*);
int32 runtime·chancap(Hchan*);
......
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