]> git.eshelyaron.com Git - emacs.git/commitdiff
* src/fns.c: Use `EQ (key, Qunbound)` to check if a slot is in use
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 26 Jul 2019 18:24:02 +0000 (14:24 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 26 Jul 2019 19:03:03 +0000 (15:03 -0400)
(make_hash_table): Use Qunbound for the key_and_value table.
(maybe_resize_hash_table): Set new key_and_value slots to Qunbound.
(hash_table_rehash): Don't bother copying the old table of hashes since
we're recomputing it completely.
(hash_table_rehash): Use hash_rehash_needed_p more.
(hash_put): Add assertion that the slot was indeed considered empty.
(hash_remove_from_table, hash_clear, sweep_weak_table): Set empty
slot's key to Qunbound.
(Fmaphash): Use `EQ (key, Qunbound)` to check if a slot is in use.

* src/lisp.h (struct Lisp_Hash_Table): Update comments.

src/fns.c
src/lisp.h

index 49ec0a8537827c13b92929f4492202d93036be38..3c85dbeae532efd26eaf16e0ec6f9fb5bd3d7502 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -4119,7 +4119,7 @@ make_hash_table (struct hash_table_test test, EMACS_INT size,
   h->rehash_threshold = rehash_threshold;
   h->rehash_size = rehash_size;
   h->count = 0;
-  h->key_and_value = make_nil_vector (2 * size);
+  h->key_and_value = make_vector (2 * size, Qunbound);
   h->hash = make_nil_vector (size);
   h->next = make_vector (size, make_fixnum (-1));
   h->index = make_vector (hash_index_size (h, size), make_fixnum (-1));
@@ -4199,9 +4199,16 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
        gc_aset (next, i, make_fixnum (i + 1));
       gc_aset (next, next_size - 1, make_fixnum (-1));
       ptrdiff_t index_size = hash_index_size (h, next_size);
+
+      /* Build the new&larger key_and_value vector, making sure the new
+         fields are initialized to `unbound`.  */
       Lisp_Object key_and_value
-       = larger_vector (h->key_and_value, 2 * (next_size - old_size),
-                        2 * next_size);
+       = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size),
+                          2 * next_size);
+      for (ptrdiff_t i = ASIZE (h->key_and_value);
+            i < ASIZE (key_and_value); i++)
+        ASET (key_and_value, i, Qunbound);
+
       Lisp_Object hash = larger_vector (h->hash, next_size - old_size,
                                        next_size);
       h->index = make_vector (index_size, make_fixnum (-1));
@@ -4241,17 +4248,16 @@ hash_table_rehash (struct Lisp_Hash_Table *h)
      (bug#36447).  */
   h->next = Fcopy_sequence (h->next);
   h->index = Fcopy_sequence (h->index);
-  h->hash = Fcopy_sequence (h->hash);
+  h->hash = make_nil_vector (size);
 
   /* Recompute the actual hash codes for each entry in the table.
      Order is still invalid.  */
   for (ptrdiff_t i = 0; i < size; ++i)
-    if (!NILP (HASH_HASH (h, i)))
-      {
-        Lisp_Object key = HASH_KEY (h, i);
-       Lisp_Object hash_code = h->test.hashfn (key, h);
-       set_hash_hash_slot (h, i, hash_code);
-      }
+    {
+      Lisp_Object key = HASH_KEY (h, i);
+      if (!EQ (key, Qunbound))
+       set_hash_hash_slot (h, i, h->test.hashfn (key, h));
+    }
 
   /* Reset the index so that any slot we don't fill below is marked
      invalid.  */
@@ -4271,7 +4277,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h)
   /* Finally, mark the hash table as having a valid hash order.
      Do this last so that if we're interrupted, we retry on next
      access. */
-  eassert (h->count < 0);
+  eassert (hash_rehash_needed_p (h));
   h->count = -h->count;
   eassert (!hash_rehash_needed_p (h));
 }
@@ -4329,6 +4335,8 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
 
   /* Store key/value in the key_and_value vector.  */
   i = h->next_free;
+  eassert (NILP (HASH_HASH (h, i)));
+  eassert (EQ (Qunbound, (HASH_KEY (h, i))));
   h->next_free = HASH_NEXT (h, i);
   set_hash_key_slot (h, i, key);
   set_hash_value_slot (h, i, value);
@@ -4372,7 +4380,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
 
          /* Clear slots in key_and_value and add the slots to
             the free list.  */
-         set_hash_key_slot (h, i, Qnil);
+         set_hash_key_slot (h, i, Qunbound);
          set_hash_value_slot (h, i, Qnil);
          set_hash_hash_slot (h, i, Qnil);
          set_hash_next_slot (h, i, h->next_free);
@@ -4399,7 +4407,7 @@ hash_clear (struct Lisp_Hash_Table *h)
       for (i = 0; i < size; ++i)
        {
          set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
-         set_hash_key_slot (h, i, Qnil);
+         set_hash_key_slot (h, i, Qunbound);
          set_hash_value_slot (h, i, Qnil);
          set_hash_hash_slot (h, i, Qnil);
        }
@@ -4458,6 +4466,8 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
 
          if (remove_entries_p)
            {
+              eassert (!remove_p
+                       == (key_known_to_survive_p && value_known_to_survive_p));
              if (remove_p)
                {
                  /* Take out of collision chain.  */
@@ -4471,7 +4481,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
                  h->next_free = i;
 
                  /* Clear key, value, and hash.  */
-                 set_hash_key_slot (h, i, Qnil);
+                 set_hash_key_slot (h, i, Qunbound);
                  set_hash_value_slot (h, i, Qnil);
                   set_hash_hash_slot (h, i, Qnil);
 
@@ -5009,8 +5019,11 @@ FUNCTION is called with two arguments, KEY and VALUE.
   struct Lisp_Hash_Table *h = check_hash_table (table);
 
   for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
-    if (!NILP (HASH_HASH (h, i)))
-      call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i));
+    {
+      Lisp_Object k = HASH_KEY (h, i);
+      if (!EQ (k, Qunbound))
+        call2 (function, k, HASH_VALUE (h, i));
+    }
 
   return Qnil;
 }
index 17495777378d358b9251cd581250bb134099a36f..680798621cac79468820557c8c0928cf2f6c5941 100644 (file)
@@ -2274,8 +2274,8 @@ struct Lisp_Hash_Table
      weakness of the table.  */
   Lisp_Object weak;
 
-  /* Vector of hash codes.  If hash[I] is nil, this means that the
-     I-th entry is unused.  */
+  /* Vector of hash codes.
+     If the I-th entry is unused, then hash[I] should be nil.  */
   Lisp_Object hash;
 
   /* Vector used to chain entries.  If entry I is free, next[I] is the
@@ -2323,6 +2323,7 @@ struct Lisp_Hash_Table
 
   /* Vector of keys and values.  The key of item I is found at index
      2 * I, the value is found at index 2 * I + 1.
+     If the key is equal to Qunbound, then this slot is unused.
      This is gc_marked specially if the table is weak.  */
   Lisp_Object key_and_value;