shithub: mc

Download patch

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)