Index: trunk/src/emx/src/emxomf/stabshll.c
===================================================================
--- trunk/src/emx/src/emxomf/stabshll.c	(revision 372)
+++ trunk/src/emx/src/emxomf/stabshll.c	(revision 373)
@@ -110,5 +110,6 @@
   ty_class,                     /* A C++ class */
   ty_memfunc,                   /* A C++ member function */
-  ty_baseclass                  /* A C++ base class */
+  ty_baseclass,                 /* A C++ base class */
+  ty_max
 };
 
@@ -149,4 +150,5 @@
   int index;                    /* The HLL index for this type */
   struct type *next;            /* All types are chained in a single list */
+  struct type *nexthash;        /* All types are chained in the hash list */
   union
     {
@@ -295,4 +297,10 @@
 
 static struct type *type_head;
+#define TYPE_HASH_MAX   128
+static struct type *atype_tag[TYPE_HASH_MAX + 1];
+#ifdef HASH_DEBUG
+static int          ctypes = 0;
+static int          ctype_tag[TYPE_HASH_MAX + 1];
+#endif
 
 /* This growing array keeps track of stabs vs. internal types.  It is
@@ -560,4 +568,39 @@
 }
 
+/**
+ * Try calculate a good hash (yeah sure).
+ *
+ * @returns hash index.
+ * @param   t     type
+ */
+static unsigned type_hash (struct type *t)
+{
+  unsigned uhash;
+  switch (t->tag)
+    {
+      case ty_alias:        uhash = (unsigned)t->d.alias; break;
+      case ty_stabs_ref:    uhash = (unsigned)t->d.stabs_ref; break;
+      case ty_prim:         uhash = (unsigned)t->index; break;
+      case ty_pointer:      uhash = (unsigned)t->d.pointer; break;
+      case ty_ref:          uhash = (unsigned)t->d.ref; break;
+      case ty_struc:        uhash = (unsigned)t->d.struc.name; break;
+      case ty_class:        uhash = (unsigned)t->d.class.name; break;
+      case ty_enu:          uhash = (unsigned)t->d.enu.name; break;
+      case ty_array:        uhash = (unsigned)t->d.array.etype; break;
+      case ty_bits:         uhash = (unsigned)t->d.bits.type; break;
+      case ty_func:         uhash = (unsigned)t->d.func.args; break;
+      case ty_args:         uhash = (unsigned)t->d.args.list + t->d.args.count; break;
+      case ty_types:        uhash = (unsigned)t->d.types.list + t->d.types.count; break;
+      case ty_fields:       uhash = (unsigned)t->d.fields.list + t->d.fields.count; break;
+      case ty_member:       uhash = (unsigned)t->d.member.type + t->d.member.offset + t->d.member.flags; break;
+      case ty_values:       uhash = (unsigned)t->d.values.list + t->d.values.count; break;
+      case ty_memfunc:      uhash = (unsigned)t->d.memfunc.name + t->d.memfunc.offset; break;
+      case ty_baseclass:    uhash = (unsigned)t->d.baseclass.type + t->d.baseclass.offset; break;
+      default:
+        return 0;
+    }
+  return (uhash ^ (uhash >> 13)) & (TYPE_HASH_MAX - 1);
+}
+
 
 /* Add a new internal type to the list of internal types.  If an
@@ -566,144 +609,157 @@
    pointer to that type is returned.  It isn't worth my while to
    improve the speed of this function, for instance by using
-   hashing. */
+   hashing.
+
+   Actually it is worth while optimizing it as it takes 85% of the
+   time here... or rather it was. */
 
 static struct type *type_add (struct type *src)
 {
+  unsigned ihash;
   struct type *p;
   int i;
 
-  for (p = type_head; p != NULL; p = p->next)
-    if (p->tag == src->tag)
-      switch (p->tag)
-        {
-        case ty_alias:
-          if (p->d.alias == src->d.alias)
-            return p;
-          break;
-        case ty_stabs_ref:
-          if (p->d.stabs_ref == src->d.stabs_ref)
-            return p;
-          break;
-        case ty_prim:
-          if (p->index == src->index)
-            return p;
-          break;
-        case ty_pointer:
-          if (p->d.pointer == src->d.pointer)
-            return p;
-          break;
-        case ty_ref:
-          if (p->d.ref == src->d.ref)
-            return p;
-          break;
-        case ty_struc:
-          if (p->d.struc.fields == src->d.struc.fields
-              && p->d.struc.types == src->d.struc.types
-              && p->d.struc.name == src->d.struc.name
-              && p->d.struc.flags == src->d.struc.flags)
-            return p;
-          break;
-        case ty_class:
-          if (p->d.class.members == src->d.class.members
-              && p->d.class.name == src->d.class.name)
-            return p;
-          break;
-        case ty_enu:
-          if (p->d.enu.type == src->d.enu.type
-              && p->d.enu.values == src->d.enu.values
-              && p->d.enu.name == src->d.enu.name)
-            return p;
-          break;
-        case ty_array:
-          if (p->d.array.etype == src->d.array.etype
-              && p->d.array.itype == src->d.array.itype
-              && p->d.array.first == src->d.array.first
-              && p->d.array.last == src->d.array.last)
-            return p;
-          break;
-        case ty_bits:
-          if (p->d.bits.type == src->d.bits.type
-              && p->d.bits.start == src->d.bits.start
-              && p->d.bits.count == src->d.bits.count)
-            return p;
-          break;
-        case ty_func:
-          if (p->d.func.ret == src->d.func.ret
-              && p->d.func.args == src->d.func.args
-              && p->d.func.domain == src->d.func.domain
-              && p->d.func.arg_count == src->d.func.arg_count)
-            return p;
-          break;
-        case ty_args:
-          if (p->d.args.count == src->d.args.count)
-            {
-              for (i = 0; i < p->d.args.count; ++i)
-                if (p->d.args.list[i] != src->d.args.list[i])
-                  break;
-              if (i >= p->d.args.count)
-                return p;
-            }
-          break;
-        case ty_types:
-          if (p->d.types.count == src->d.types.count)
-            {
-              for (i = 0; i < p->d.types.count; ++i)
-                if (p->d.types.list[i] != src->d.types.list[i])
-                  break;
-              if (i >= p->d.types.count)
-                return p;
-            }
-          break;
-        case ty_fields:
-          if (p->d.fields.count == src->d.fields.count)
-            {
-              for (i = 0; i < p->d.fields.count; ++i)
-                if (p->d.fields.list[i].offset != src->d.fields.list[i].offset
-                    || p->d.fields.list[i].name != src->d.fields.list[i].name)
-                  break;
-              if (i >= p->d.fields.count)
-                return p;
-            }
-          break;
-        case ty_member:
-          if (p->d.member.type == src->d.member.type
-              && p->d.member.offset == src->d.member.offset
-              && p->d.member.flags == src->d.member.flags
-              && p->d.member.name == src->d.member.name
-              && p->d.member.sname == src->d.member.sname)
-            return p;
-          break;
-        case ty_values:
-          if (p->d.values.count == src->d.values.count)
-            {
-              for (i = 0; i < p->d.values.count; ++i)
-                if (p->d.values.list[i].index != src->d.values.list[i].index
-                    || p->d.values.list[i].name != src->d.values.list[i].name)
-                  break;
-              if (i >= p->d.values.count)
-                return p;
-            }
-          break;
-        case ty_memfunc:
-          if (p->d.memfunc.type == src->d.memfunc.type
-              && p->d.memfunc.offset == src->d.memfunc.offset
-              && p->d.memfunc.flags == src->d.memfunc.flags
-              && p->d.memfunc.name == src->d.memfunc.name
-              && p->d.memfunc.mnglname == src->d.memfunc.mnglname)
-            return p;
-          break;
-        case ty_baseclass:
-          if (p->d.baseclass.type == src->d.baseclass.type
-              && p->d.baseclass.offset == src->d.baseclass.offset
-              && p->d.baseclass.flags == src->d.baseclass.flags)
-            return p;
-          break;
-        default:
-          abort ();
-        }
+  ihash = type_hash(src);
+  for (p = atype_tag[ihash]; p != NULL; p = p->nexthash)
+    switch (src->tag)
+      {
+      case ty_alias:
+        if (p->d.alias == src->d.alias)
+          return p;
+        break;
+      case ty_stabs_ref:
+        if (p->d.stabs_ref == src->d.stabs_ref)
+          return p;
+        break;
+      case ty_prim:
+        if (p->index == src->index)
+          return p;
+        break;
+      case ty_pointer:
+        if (p->d.pointer == src->d.pointer)
+          return p;
+        break;
+      case ty_ref:
+        if (p->d.ref == src->d.ref)
+          return p;
+        break;
+      case ty_struc:
+        if (p->d.struc.fields == src->d.struc.fields
+            && p->d.struc.types == src->d.struc.types
+            && p->d.struc.name == src->d.struc.name
+            && p->d.struc.flags == src->d.struc.flags)
+          return p;
+        break;
+      case ty_class:
+        if (p->d.class.members == src->d.class.members
+            && p->d.class.name == src->d.class.name)
+          return p;
+        break;
+      case ty_enu:
+        if (p->d.enu.type == src->d.enu.type
+            && p->d.enu.values == src->d.enu.values
+            && p->d.enu.name == src->d.enu.name)
+          return p;
+        break;
+      case ty_array:
+        if (p->d.array.etype == src->d.array.etype
+            && p->d.array.itype == src->d.array.itype
+            && p->d.array.first == src->d.array.first
+            && p->d.array.last == src->d.array.last)
+          return p;
+        break;
+      case ty_bits:
+        if (p->d.bits.type == src->d.bits.type
+            && p->d.bits.start == src->d.bits.start
+            && p->d.bits.count == src->d.bits.count)
+          return p;
+        break;
+      case ty_func:
+        if (p->d.func.ret == src->d.func.ret
+            && p->d.func.args == src->d.func.args
+            && p->d.func.domain == src->d.func.domain
+            && p->d.func.arg_count == src->d.func.arg_count)
+          return p;
+        break;
+      case ty_args:
+        if (p->d.args.count == src->d.args.count)
+          {
+            for (i = 0; i < p->d.args.count; ++i)
+              if (p->d.args.list[i] != src->d.args.list[i])
+                break;
+            if (i >= p->d.args.count)
+              return p;
+          }
+        break;
+      case ty_types:
+        if (p->d.types.count == src->d.types.count)
+          {
+            for (i = 0; i < p->d.types.count; ++i)
+              if (p->d.types.list[i] != src->d.types.list[i])
+                break;
+            if (i >= p->d.types.count)
+              return p;
+          }
+        break;
+      case ty_fields:
+        if (p->d.fields.count == src->d.fields.count)
+          {
+            for (i = 0; i < p->d.fields.count; ++i)
+              if (p->d.fields.list[i].offset != src->d.fields.list[i].offset
+                  || p->d.fields.list[i].name != src->d.fields.list[i].name)
+                break;
+            if (i >= p->d.fields.count)
+              return p;
+          }
+        break;
+      case ty_member:
+        if (p->d.member.type == src->d.member.type
+            && p->d.member.offset == src->d.member.offset
+            && p->d.member.flags == src->d.member.flags
+            && p->d.member.name == src->d.member.name
+            && p->d.member.sname == src->d.member.sname)
+          return p;
+        break;
+      case ty_values:
+        if (p->d.values.count == src->d.values.count)
+          {
+            for (i = 0; i < p->d.values.count; ++i)
+              if (p->d.values.list[i].index != src->d.values.list[i].index
+                  || p->d.values.list[i].name != src->d.values.list[i].name)
+                break;
+            if (i >= p->d.values.count)
+              return p;
+          }
+        break;
+      case ty_memfunc:
+        if (p->d.memfunc.type == src->d.memfunc.type
+            && p->d.memfunc.offset == src->d.memfunc.offset
+            && p->d.memfunc.flags == src->d.memfunc.flags
+            && p->d.memfunc.name == src->d.memfunc.name
+            && p->d.memfunc.mnglname == src->d.memfunc.mnglname)
+          return p;
+        break;
+      case ty_baseclass:
+        if (p->d.baseclass.type == src->d.baseclass.type
+            && p->d.baseclass.offset == src->d.baseclass.offset
+            && p->d.baseclass.flags == src->d.baseclass.flags)
+          return p;
+        break;
+      default:
+        fprintf (stderr, "borked!\n");
+        abort ();
+      }
+
+#ifdef HASH_DEBUG
+  ctypes++;
+  ctype_tag[ihash]++;
+#endif
+
   p = xmalloc (sizeof (*p));
   *p = *src;
   p->next = type_head;
   type_head = p;
+  p->nexthash = atype_tag[ihash];
+  atype_tag[ihash] = p;
   switch (src->tag)
     {
@@ -3535,4 +3591,10 @@
       }
 
+#ifdef HASH_DEBUG
+fprintf(stderr, "ctypes=%d\n", ctypes);
+for (i = 0; i < TYPE_HASH_MAX; i++)
+  fprintf(stderr, "%2d - %d\n", i, ctype_tag[i]);
+#endif
+
   /* Create tags for structures, unions and classes. */
 
@@ -3598,4 +3660,5 @@
     }
   type_head = NULL;
+  memset (&atype_tag, 0, sizeof(atype_tag));
   strpool_free (str_pool);
   str_pool = NULL;
