diff --git a/src/hashmap.c b/src/hashmap.c
index 4729ea18c42a367316c5a5e048bf819266814cab..3ebf9271dcc2060de0731c00a1c362a877ee64a7 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -248,15 +248,15 @@ hashmap_element_t *hashmap_find(hashmap_t *m, hashmap_key_t key, int create_new,
 /**
  * @brief Grows the hashmap and rehashes all the elements
  */
-void hashmap_grow(hashmap_t *m) {
+void hashmap_grow(hashmap_t *m, size_t new_size) {
   /* Hold on to the old data. */
   const size_t old_table_size = m->table_size;
   hashmap_chunk_t **old_chunks = m->chunks;
 
   /* Re-allocate the chunk array. */
-  m->table_size *= HASHMAP_GROWTH_FACTOR;
-  m->nr_chunks = (m->table_size + HASHMAP_ELEMENTS_PER_CHUNK - 1) /
-                 HASHMAP_ELEMENTS_PER_CHUNK;
+  if (new_size == 0) new_size = m->table_size * HASHMAP_GROWTH_FACTOR;
+  m->nr_chunks =
+      (new_size + HASHMAP_ELEMENTS_PER_CHUNK - 1) / HASHMAP_ELEMENTS_PER_CHUNK;
   m->table_size = m->nr_chunks * HASHMAP_ELEMENTS_PER_CHUNK;
 
   if (HASHMAP_DEBUG_OUTPUT) {
@@ -273,6 +273,11 @@ void hashmap_grow(hashmap_t *m) {
   /* Reset size. */
   m->size = 0;
 
+  /* Buffer of stray elements, in case we get overflows while re-hashing. */
+  hashmap_element_t *strays = NULL;
+  size_t strays_count = 0;
+  size_t strays_size = 0;
+
   /* Iterate over the chunks and add their entries to the new table. */
   for (size_t cid = 0; cid < old_table_size / HASHMAP_ELEMENTS_PER_CHUNK;
        cid++) {
@@ -296,11 +301,29 @@ void hashmap_grow(hashmap_t *m) {
           hashmap_element_t *new_element =
               hashmap_find(m, element->key, /*create_new=*/1,
                            /*chain_length=*/NULL, /*created_new_element=*/NULL);
-          if (!new_element) {
-            /* TODO(pedro): Deal with this type of failure more elegantly. */
-            error("Failed to re-hash element.");
+
+          if (new_element) {
+            new_element->value = element->value;
+          }
+          /* If copying failed, then we have an overflow in the new hashmap.
+             If this happens, store the offending element in the strays buffer
+             for now. */
+          else {
+            /* (Re)allocate strays buffer? */
+            if (strays_count == strays_size) {
+              hashmap_element_t *temp_buff;
+              strays_size = strays_size ? strays_size * 2 : 10;
+              if ((temp_buff = (hashmap_element_t *)swift_malloc(
+                       "hashmap_strays",
+                       sizeof(hashmap_element_t) * strays_size)) == NULL)
+                error("Failed to (re)allocate strays buffer.");
+              memcpy(temp_buff, strays,
+                     sizeof(hashmap_element_t) * strays_count);
+              swift_free("hashmap_strays", strays);
+              strays = temp_buff;
+            }
+            strays[strays_count++] = *element;
           }
-          new_element->value = element->value;
         }
       }
     }
@@ -311,10 +334,18 @@ void hashmap_grow(hashmap_t *m) {
 
   /* Free the old list of chunks. */
   swift_free("hashmap", old_chunks);
+
+  /* If we have any strays, add them back to the hashmap. This will inevitably
+     trigger a rehashing, but that's not our problem. */
+  if (strays_count) {
+    for (size_t k = 0; k < strays_count; k++) {
+      hashmap_put(m, strays[k].key, strays[k].value);
+    }
+    swift_free("hashmap_strays", strays);
+  }
 }
 
 void hashmap_put(hashmap_t *m, hashmap_key_t key, hashmap_value_t value) {
-
   /* Try to find an element for the given key. */
   hashmap_element_t *element =
       hashmap_find(m, key, /*create_new=*/1, /*chain_length=*/NULL,
@@ -322,7 +353,7 @@ void hashmap_put(hashmap_t *m, hashmap_key_t key, hashmap_value_t value) {
 
   /* Loop around, trying to find our place in the world. */
   while (!element) {
-    hashmap_grow(m);
+    hashmap_grow(m, 0);
     element = hashmap_find(m, key, /*create_new=*/1, /*chain_length=*/NULL,
                            /*created_new_element=*/NULL);
   }
@@ -332,13 +363,12 @@ void hashmap_put(hashmap_t *m, hashmap_key_t key, hashmap_value_t value) {
 }
 
 hashmap_value_t *hashmap_get(hashmap_t *m, hashmap_key_t key) {
-
   /* Look for the given key. */
   hashmap_element_t *element =
       hashmap_find(m, key, /*create_new=*/1, /*chain_length=*/NULL,
                    /*created_new_element=*/NULL);
   while (!element) {
-    hashmap_grow(m);
+    hashmap_grow(m, 0);
     element = hashmap_find(m, key, /*create_new=*/1, /*chain_length=*/NULL,
                            /*created_new_element=*/NULL);
   }
@@ -351,7 +381,7 @@ hashmap_value_t *hashmap_get_new(hashmap_t *m, hashmap_key_t key,
   hashmap_element_t *element = hashmap_find(
       m, key, /*create_new=*/1, /*chain_length=*/NULL, created_new_element);
   while (!element) {
-    hashmap_grow(m);
+    hashmap_grow(m, 0);
     element = hashmap_find(m, key, /*create_new=*/1, /*chain_length=*/NULL,
                            created_new_element);
   }
diff --git a/src/hashmap.h b/src/hashmap.h
index 2a4cdeaf64154d838e40df5a14f61f1084473029..40bb309e552266942afdacd79b5cb8268132a74f 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -33,6 +33,9 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+/* Local headers. */
+#include "align.h"
+
 // Type used for chunk bitmasks.
 typedef size_t hashmap_mask_t;
 
@@ -83,7 +86,7 @@ typedef struct _hashmap_chunk {
     void *next;
   };
   hashmap_element_t data[HASHMAP_ELEMENTS_PER_CHUNK];
-} hashmap_chunk_t;
+} SWIFT_STRUCT_ALIGN hashmap_chunk_t;
 
 /* A hashmap has some maximum size and current size,
  * as well as the data to hold. */
@@ -117,6 +120,18 @@ typedef void (*hashmap_mapper_t)(hashmap_key_t, hashmap_value_t *, void *);
  */
 void hashmap_init(hashmap_t *m);
 
+/**
+ * @brief Re-size the hashmap.
+ *
+ * Note that the hashmap size does not necessarily correspond to its
+ * capacity, since it will grow if too many collisions occur. As a rule
+ * of thumb, allocate twice as many elements as you think you will need.
+ *
+ * @param size New table size. If zero, the current size will be increase
+ *             by a fixed rate.
+ */
+void hashmap_grow(hashmap_t *m, size_t size);
+
 /**
  * @brief Add a key/value pair to the hashmap, overwriting whatever was
  * previously there.