Commit b3dd22fe authored by Ken Thompson's avatar Ken Thompson

adjustable hash code in

typecheck of composit literals
to get rid of n^2 behavior.

R=rsc
CC=golang-dev
https://golang.org/cl/3208041
parent 1fab0cd1
...@@ -1808,20 +1808,57 @@ indexdup(Node *n, Node *hash[], ulong nhash) ...@@ -1808,20 +1808,57 @@ indexdup(Node *n, Node *hash[], ulong nhash)
hash[h] = n; hash[h] = n;
} }
static int
prime(ulong h)
{
ulong n, sr;
sr = h;
for(n=0; n<3; n++)
sr = (sr + h/sr)/2;
for(n=3; n<sr; n+=2)
if(h%n == 0)
return 0;
return 1;
}
static ulong
inithash(Node *n, Node ***hash, Node **autohash, ulong nautohash)
{
ulong h;
NodeList *ll;
h = 0;
for(ll=n->list; ll; ll=ll->next)
h++;
h = 9*h/8;
if(h <= nautohash) {
*hash = autohash;
memset(*hash, 0, nautohash * sizeof(**hash));
return nautohash;
}
while(!prime(h))
h++;
*hash = mal(h * sizeof(**hash));
memset(*hash, 0, h * sizeof(**hash));
return h;
}
static void static void
typecheckcomplit(Node **np) typecheckcomplit(Node **np)
{ {
int bad, i, len, nerr; int bad, i, len, nerr;
Node *l, *n, *hash[101]; Node *l, *n, **hash;
NodeList *ll; NodeList *ll;
Type *t, *f, *pushtype; Type *t, *f, *pushtype;
Sym *s; Sym *s;
int32 lno; int32 lno;
ulong nhash;
Node *autohash[101];
n = *np; n = *np;
lno = lineno; lno = lineno;
memset(hash, 0, sizeof hash);
if(n->right == N) { if(n->right == N) {
if(n->list != nil) if(n->list != nil)
setlineno(n->list->n); setlineno(n->list->n);
...@@ -1861,6 +1898,8 @@ typecheckcomplit(Node **np) ...@@ -1861,6 +1898,8 @@ typecheckcomplit(Node **np)
break; break;
case TARRAY: case TARRAY:
nhash = inithash(n, &hash, autohash, nelem(autohash));
len = 0; len = 0;
i = 0; i = 0;
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
...@@ -1881,7 +1920,7 @@ typecheckcomplit(Node **np) ...@@ -1881,7 +1920,7 @@ typecheckcomplit(Node **np)
i = -(1<<30); // stay negative for a while i = -(1<<30); // stay negative for a while
} }
if(i >= 0) if(i >= 0)
indexdup(l->left, hash, nelem(hash)); indexdup(l->left, hash, nhash);
i++; i++;
if(i > len) { if(i > len) {
len = i; len = i;
...@@ -1906,6 +1945,8 @@ typecheckcomplit(Node **np) ...@@ -1906,6 +1945,8 @@ typecheckcomplit(Node **np)
break; break;
case TMAP: case TMAP:
nhash = inithash(n, &hash, autohash, nelem(autohash));
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
l = ll->n; l = ll->n;
setlineno(l); setlineno(l);
...@@ -1918,7 +1959,7 @@ typecheckcomplit(Node **np) ...@@ -1918,7 +1959,7 @@ typecheckcomplit(Node **np)
typecheck(&l->left, Erv); typecheck(&l->left, Erv);
defaultlit(&l->left, t->down); defaultlit(&l->left, t->down);
l->left = assignconv(l->left, t->down, "map key"); l->left = assignconv(l->left, t->down, "map key");
keydup(l->left, hash, nelem(hash)); keydup(l->left, hash, nhash);
if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T) if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
l->right->right = typenod(pushtype); l->right->right = typenod(pushtype);
...@@ -1953,6 +1994,8 @@ typecheckcomplit(Node **np) ...@@ -1953,6 +1994,8 @@ typecheckcomplit(Node **np)
if(f != nil) if(f != nil)
yyerror("too few values in struct initializer"); yyerror("too few values in struct initializer");
} else { } else {
nhash = inithash(n, &hash, autohash, nelem(autohash));
// keyed list // keyed list
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
l = ll->n; l = ll->n;
...@@ -1983,7 +2026,7 @@ typecheckcomplit(Node **np) ...@@ -1983,7 +2026,7 @@ typecheckcomplit(Node **np)
continue; continue;
} }
s = f->sym; s = f->sym;
fielddup(newname(s), hash, nelem(hash)); fielddup(newname(s), hash, nhash);
l->right = assignconv(l->right, f->type, "field value"); l->right = assignconv(l->right, f->type, "field value");
} }
} }
......
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