ref: 1ac199a3e2c150873279adf3a36f9a8f94e8fd60
parent: 3d20a6d5e0c554e9f3d0d3f504f4dfb28901ebb7
author: Ori Bernstein <[email protected]>
date: Thu Oct 10 18:37:25 EDT 2013
Deduplicate types when loading usefiles.a
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -100,13 +100,6 @@
}
-static int nameeq(Node *a, Node *b)
-{
- if (a == b)
- return 1;
- return streq(a->name.ns, b->name.ns) && streq(a->name.name, b->name.name);
-}
-
/* Set a scope's enclosing scope up correctly.
* We don't do this in the parser for some reason. */
static void setsuper(Stab *st, Stab *super)
--- a/parse/node.c
+++ b/parse/node.c
@@ -325,6 +325,26 @@
return NULL;
}
+/* name hashing */
+ulong namehash(void *p)
+{
+ Node *n;
+
+ n = p;
+ return strhash(namestr(n)) ^ strhash(n->name.ns);
+}
+
+int nameeq(void *p1, void *p2)
+{
+ Node *a, *b;
+ a = p1;
+ b = p2;
+ if (a == b)
+ return 1;
+
+ return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
+}
+
void setns(Node *n, char *ns)
{
n->name.ns = strdup(ns);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -115,7 +115,8 @@
size_t ncstrlist; /* The length of the constraint list above */
int isgeneric; /* Tyname: whether this is generic or not */
- int issynth; /* Tyname: whether this is synthesized or not */
+ int issynth; /* Tyname: whether this is synthesized or not */
+ int ishidden; /* Tyname: whether this is hidden or not */
Type **param; /* Tyname: type parameters that match the type args */
size_t nparam; /* Tyname: count of type parameters */
Type **arg; /* Tyname: type arguments instantiated */
@@ -314,6 +315,8 @@
int inteq(uint64_t a, uint64_t b);
ulong tyhash(void *t);
int tyeq(void *a, void *b);
+ulong namehash(void *t);
+int nameeq(void *a, void *b);
/* util functions */
void *zalloc(size_t size);
@@ -344,6 +347,7 @@
Stab *getns(Stab *st, Node *n);
Stab *getns_str(Stab *st, char *n);
Node *getdcl(Stab *st, Node *n);
+Type *gettype_l(Stab *st, Node *n);
Type *gettype(Stab *st, Node *n);
Cstr *getcstr(Stab *st, Node *n);
Ucon *getucon(Stab *st, Node *n);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -48,13 +48,15 @@
stabstkoff--;
}
-/* name hashing */
-static ulong namehash(void *n)
+/* name hashing: we want namespaced lookups to find the
+ * name even if we haven't set the namespace up, since
+ * we can update it after the fact. */
+static ulong nsnamehash(void *n)
{
return strhash(namestr(n));
}
-static int nameeq(void *a, void *b)
+static int nsnameeq(void *a, void *b)
{
return a == b || !strcmp(namestr(a), namestr(b));
}
@@ -65,9 +67,9 @@
st = zalloc(sizeof(Stab));
st->ns = mkht(strhash, streq);
- st->dcl = mkht(namehash, nameeq);
- st->ty = mkht(namehash, nameeq);
- st->uc = mkht(namehash, nameeq);
+ st->dcl = mkht(nsnamehash, nsnameeq);
+ st->ty = mkht(nsnamehash, nsnameeq);
+ st->uc = mkht(nsnamehash, nsnameeq);
return st;
}
@@ -91,7 +93,7 @@
if ((s = htget(st->dcl, n))) {
/* record that this is in the closure of this scope */
if (!st->closure)
- st->closure = mkht(namehash, nameeq);
+ st->closure = mkht(nsnamehash, nsnameeq);
if (st != orig && !n->decl.isglobl)
htput(st->closure, s->decl.name, s);
return s;
@@ -101,6 +103,16 @@
return NULL;
}
+Type *gettype_l(Stab *st, Node *n)
+{
+ Tydefn *t;
+
+ if ((t = htget(st->ty, n)))
+ return t->type;
+ return NULL;
+}
+
+
Type *gettype(Stab *st, Node *n)
{
Tydefn *t;
@@ -183,11 +195,13 @@
Tydefn *td;
if (gettype(st, n))
- fatal(n->line, "Type %s already defined", namestr(n));
+ fatal(n->line, "Type %s already defined", tystr(gettype(st, n)));
td = xalloc(sizeof(Tydefn));
td->line = n->line;
td->name = n;
td->type = t;
+ if (st->name)
+ setns(n, namestr(st->name));
htput(st->ty, td->name, td);
}
--- a/parse/type.c
+++ b/parse/type.c
@@ -462,6 +462,8 @@
}
break;
case Tyname:
+ if (t->name->name.ns)
+ p += snprintf(p, end - p, "%s.", t->name->name.ns);
p += snprintf(p, end - p, "%s", namestr(t->name));
if (t->isgeneric) {
arg = t->param;
--- a/parse/use.c
+++ b/parse/use.c
@@ -21,6 +21,7 @@
static Node *unpickle(FILE *fd);
/* type fixup list */
+static Htab *dedup; /* map from name -> type, contains all Tynames loaded ever */
static Htab *tidmap; /* map from tid -> type */
static Type ***typefixdest; /* list of types we need to replace */
static size_t ntypefixdest; /* size of replacement list */
@@ -181,6 +182,7 @@
return;
}
wrbyte(fd, ty->type);
+ wrbyte(fd, ty->vis);
/* tid is generated; don't write */
/* cstrs are left out for now: FIXME */
wrint(fd, ty->nsub);
@@ -261,6 +263,8 @@
t = rdbyte(fd);
ty = mktype(-1, t);
+ if (rdbyte(fd) == Vishidden)
+ ty->ishidden = 1;
/* tid is generated; don't write */
/* cstrs are left out for now: FIXME */
ty->nsub = rdint(fd);
@@ -586,8 +590,9 @@
for (i = 0; i < ntypefixdest; i++) {
t = htget(tidmap, (void*)typefixid[i]);
if (t->type == Tyname && !t->issynth) {
- old = gettype(st, t->name);
- if (old)
+ old = htget(dedup, t->name);
+ if (old != t)
+ if (t != old)
t = old;
}
*typefixdest[i] = t;
@@ -599,7 +604,7 @@
t = htget(tidmap, (void*)typefixid[i]);
if (t->type != Tyname || t->issynth)
continue;
- old = gettype(st, t->name);
+ old = htget(dedup, t->name);
if (old && !tyeq(t, old))
fatal(-1, "Duplicate definition of type %s", tystr(old));
}
@@ -623,6 +628,8 @@
Type *t;
int c;
+ if (!dedup)
+ dedup = mkht(namehash, nameeq);
if (fgetc(f) != 'U')
return 0;
pkg = rdstr(f);
@@ -656,8 +663,10 @@
htput(tidmap, (void*)tid, t);
/* fix up types */
if (t->type == Tyname) {
- if (!gettype(s, t->name) && !t->issynth)
+ if (!gettype(st, t->name) && !t->issynth && !t->ishidden)
puttype(s, t->name, t);
+ if (!hthas(dedup, t->name))
+ htput(dedup, t->name, t);
} else if (t->type == Tyunion) {
for (i = 0; i < t->nmemb; i++)
if (!t->udecls[i]->synth)