1
0
mirror of https://github.com/golang/go synced 2024-09-25 11:10:13 -06:00
R=r
OCL=19288
CL=19288
This commit is contained in:
Ken Thompson 2008-11-14 16:24:27 -08:00
parent 23c8faaf85
commit e875055461
3 changed files with 175 additions and 8 deletions

View File

@ -358,15 +358,158 @@ ret:
lineno = lno;
}
Case*
csort(Case *l, int(*f)(Case*, Case*))
{
Case *l1, *l2, *le;
if(l == 0 || l->slink == 0)
return l;
l1 = l;
l2 = l;
for(;;) {
l2 = l2->slink;
if(l2 == 0)
break;
l2 = l2->slink;
if(l2 == 0)
break;
l1 = l1->slink;
}
l2 = l1->slink;
l1->slink = 0;
l1 = csort(l, f);
l2 = csort(l2, f);
/* set up lead element */
if((*f)(l1, l2) < 0) {
l = l1;
l1 = l1->slink;
} else {
l = l2;
l2 = l2->slink;
}
le = l;
for(;;) {
if(l1 == 0) {
while(l2) {
le->slink = l2;
le = l2;
l2 = l2->slink;
}
le->slink = 0;
break;
}
if(l2 == 0) {
while(l1) {
le->slink = l1;
le = l1;
l1 = l1->slink;
}
break;
}
if((*f)(l1, l2) < 0) {
le->slink = l1;
le = l1;
l1 = l1->slink;
} else {
le->slink = l2;
le = l2;
l2 = l2->slink;
}
}
le->slink = 0;
return l;
}
int
casecmp(Case *c1, Case *c2)
{
int w;
w = whatis(c1->scase);
if(w != whatis(c2->scase))
fatal("casecmp");
switch(w) {
case Wlitfloat:
return mpcmpfltflt(c1->scase->val.u.fval, c2->scase->val.u.fval);
case Wlitint:
return mpcmpfixfix(c1->scase->val.u.xval, c2->scase->val.u.xval);
case Wlitstr:
return cmpslit(c1->scase, c2->scase);
// case Wlitbool:
// case Wlitnil:
}
}
void
swconst(Case *sa, int nc, Node *n1, Node *tmp)
{
Case *s, *sb;
Prog *p1, *p2, *p3;
int n;
// small number of cases --
// test them sequentially
if(nc < 4) {
for(s=sa; s!=C; s=s->slink) {
setlineno(s->scase);
memset(n1, 0, sizeof(*n1));
n1->op = OEQ;
n1->left = tmp;
n1->right = s->scase;
walktype(n1, Erv);
bgen(n1, 1, s->sprog);
}
return;
}
// large number of cases --
// find the middle and recur on each half
n = nc/2;
for(s=sa; s!=C; s=s->slink) {
n--;
if(n == 0)
break;
}
n = nc/2;
sb = s->slink;
s->slink = C;
p1 = gbranch(AJMP, T); // goto midcmp
p2 = pc; // low half of switch
swconst(sa, n, n1, tmp);
p3 = gbranch(AJMP, T); // goto end
patch(p1, pc);
setlineno(s->scase);
memset(n1, 0, sizeof(*n1));
n1->op = OLE;
n1->left = tmp;
n1->right = s->scase;
walktype(n1, Erv);
bgen(n1, 1, p2);
swconst(sb, nc-n, n1, tmp); // high half of switch
patch(p3, pc);
}
void
swgen(Node *n)
{
Node *c1, *c2;
Node n1, tmp;
Case *s0, *se, *s;
Case *s0, *se, *s, *sa;
Prog *p1, *dflt;
int32 lno;
int any;
int any, nc, w;
Iter save1, save2;
// botch - put most of this code in
@ -404,7 +547,7 @@ swgen(Node *n)
patch(gbranch(AJMP, T), breakpc);
any = 1;
// over case expressions
// loop over case expressions
c2 = listfirst(&save2, &c1->left);
if(c2 == N)
dflt = pc;
@ -439,7 +582,28 @@ swgen(Node *n)
tempname(&tmp, n->ntest->type);
cgen(n->ntest, &tmp);
sa = C; // base of constant cases
nc = 0;
for(s=s0; s!=C; s=s->slink) {
switch(whatis(s->scase)) {
case Wlitfloat:
case Wlitint:
case Wlitstr:
// case Wlitbool:
// case Wlitnil:
nc++;
if(sa == C)
sa = s;
se = s;
continue;
}
if(sa != C) {
se->slink = C;
sa = csort(sa, casecmp);
swconst(sa, nc, &n1, &tmp);
nc = 0;
sa = C;
}
setlineno(s->scase);
memset(&n1, 0, sizeof(n1));
n1.op = OEQ;
@ -448,6 +612,11 @@ swgen(Node *n)
walktype(&n1, Erv);
bgen(&n1, 1, s->sprog);
}
if(sa != C) {
se->slink = C;
sa = csort(sa, casecmp);
swconst(sa, nc, &n1, &tmp);
}
if(dflt != P) {
patch(gbranch(AJMP, T), dflt);
goto ret;

View File

@ -1094,8 +1094,7 @@ loop:
goto ret;
nottop:
dump("bad top", n);
fatal("walktype: top=%d %O", top, n->op);
yyerror("didn't expect %O here", n->op);
goto ret;
badt:
@ -2360,8 +2359,7 @@ shape:
return N;
nottop:
dump("bad top", n);
fatal("mapop: top=%d %O", top, n->op);
yyerror("didn't expect %O here", n->op);
return N;
}

View File

@ -125,7 +125,7 @@ hash_init (struct hash *h,
if(datasize < sizeof (void *))
datasize = sizeof (void *);
datasize = rnd(datasize, 8);
datasize = rnd(datasize, sizeof (void *));
init_sizes (hint, &init_power, &max_power);
h->datasize = datasize;
h->max_power = max_power;