Skip to content

Commit

Permalink
gc, runtime: replace closed(c) with x, ok := <-c
Browse files Browse the repository at this point in the history
R=ken2, ken3
CC=golang-dev
https://golang.org/cl/4259064
  • Loading branch information
rsc committed Mar 11, 2011
1 parent 9f2cb86 commit 8bf34e3
Show file tree
Hide file tree
Showing 15 changed files with 260 additions and 149 deletions.
4 changes: 3 additions & 1 deletion src/cmd/gc/builtin.c.boot
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/gc/go.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -389,6 +388,7 @@ enum
ORECV,
ORUNESTR,
OSELRECV,
OSELRECV2,
OIOTA,
OREAL, OIMAG, OCOMPLEX,

Expand Down
17 changes: 13 additions & 4 deletions src/cmd/gc/go.y
Original file line number Diff line number Diff line change
Expand Up @@ -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 ':'
{
Expand Down
1 change: 0 additions & 1 deletion src/cmd/gc/lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 0 additions & 2 deletions src/cmd/gc/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/gc/range.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/gc/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
70 changes: 68 additions & 2 deletions src/cmd/gc/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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 &&
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/gc/sinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/gc/subr.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,6 @@ goopnames[] =
[OCALL] = "function call",
[OCAP] = "cap",
[OCASE] = "case",
[OCLOSED] = "closed",
[OCLOSE] = "close",
[OCOMPLEX] = "complex",
[OCOM] = "^",
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 4 additions & 8 deletions src/cmd/gc/typecheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,6 @@ typecheck(Node **np, int top)
n->type = t;
goto ret;

case OCLOSED:
case OCLOSE:
if(onearg(n, "%#O", n->op) < 0)
goto error;
Expand All @@ -934,11 +933,7 @@ typecheck(Node **np, int top)
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;
ok |= Etop;
goto ret;

case OAPPEND:
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 3 additions & 12 deletions src/cmd/gc/walk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand Down
Loading

0 comments on commit 8bf34e3

Please sign in to comment.