From 289acb4a40595b7604b1c4e07242510d2537e214 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Thu, 4 Jul 2024 19:00:18 +0000 Subject: [PATCH 4/5] implement key-or-value hash tables --- src/fns.c | 21 ++++++++++++++++- src/igc.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/src/fns.c b/src/fns.c index 221e239c639..4faa0cd51d8 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5508,6 +5508,7 @@ allocate_weak_hash_table (hash_table_weakness_t weak, ssize_t size, ssize_t inde ret->strong->index = ret->strong->entries + 3 * size; break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: ret->strong->key = ret->weak->entries; ret->strong->value = ret->weak->entries + size; ret->strong->index = ret->strong->entries + 2 * size; @@ -5661,6 +5662,7 @@ maybe_resize_weak_hash_table (struct Lisp_Weak_Hash_Table *h) strong->index = strong->entries + 3 * new_size; break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: strong->key = weak->entries; strong->value = weak->entries + new_size; strong->index = strong->entries + 2 * new_size; @@ -5742,6 +5744,11 @@ weak_hash_put (struct Lisp_Weak_Hash_Table *h, Lisp_Object key, Lisp_Object valu /* Increment count after resizing because resizing may fail. */ maybe_resize_weak_hash_table (h); + if (h->strong->weakness == Weak_Key_Or_Value) + { + Figc_add_extra_dependency (key, value, make_lisp_weak_hash_table (h)); + Figc_add_extra_dependency (value, key, make_lisp_weak_hash_table (h)); + } /* Store key/value in the key_and_value vector. */ ptrdiff_t i = XFIXNUM (h->strong->next_free); //eassert (hash_unused_entry_key_p (HASH_KEY (h, i))); @@ -6546,7 +6553,19 @@ DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0, Lisp_Object hash = weak_hash_from_key (wh, key); ptrdiff_t i = weak_hash_lookup_with_hash (wh, key, hash); if (i >= 0) - set_weak_hash_value_slot (wh, i, value); + { + if (wh->strong->weakness == Weak_Key_Or_Value) + { + Figc_remove_extra_dependency (key, table); + Figc_remove_extra_dependency (value, table); + } + set_weak_hash_value_slot (wh, i, value); + if (wh->strong->weakness == Weak_Key_Or_Value) + { + Figc_add_extra_dependency (key, value, table); + Figc_add_extra_dependency (value, key, table); + } + } else weak_hash_put (wh, key, value, hash); return value; diff --git a/src/igc.c b/src/igc.c index bc697700bf7..7a42470f061 100644 --- a/src/igc.c +++ b/src/igc.c @@ -2019,6 +2019,7 @@ fix_weak_hash_table_strong_part (mps_ss_t ss, struct Lisp_Weak_Hash_Table_Strong limit = 3 * XFIXNUM (t->table_size); break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: limit = 2 * XFIXNUM (t->table_size); break; default: @@ -2054,6 +2055,7 @@ fix_weak_hash_table_weak_part (mps_ss_t ss, struct Lisp_Weak_Hash_Table_Weak_Par limit = XFIXNUM (t->table_size); break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: limit = 2 * XFIXNUM (t->table_size); break; default: @@ -2074,7 +2076,8 @@ fix_weak_hash_table_weak_part (mps_ss_t ss, struct Lisp_Weak_Hash_Table_Weak_Par .weak = w, }; weak_hash_splat_from_table - (&pseudo_h, ((t->weakness == Weak_Key_And_Value) ? + (&pseudo_h, ((t->weakness == Weak_Key_And_Value || + t->weakness == Weak_Key_Or_Value) ? (i % XFIXNUM (t->table_size)) : i)); } } @@ -3990,6 +3993,7 @@ igc_alloc_weak_hash_table_strong_part (hash_table_weakness_t weak, total_size = 3 * size + ((ptrdiff_t)1 << index_bits); break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: total_size = 2 * size + ((ptrdiff_t)1 << index_bits); break; default: @@ -4014,6 +4018,7 @@ igc_alloc_weak_hash_table_weak_part (hash_table_weakness_t weak, total_size = size; break; case Weak_Key_And_Value: + case Weak_Key_Or_Value: total_size = 2 * size; break; default: @@ -4274,8 +4279,8 @@ DEFUN ("igc--roots", Figc__roots, Sigc__roots, 0, 0, 0, doc : /* */) } DEFUN ("igc-add-extra-dependency", Figc_add_extra_dependency, - Sigc_add_extra_dependency, 2, 2, 0, doc : /* */) - (Lisp_Object obj, Lisp_Object dependency) + Sigc_add_extra_dependency, 3, 3, 0, doc : /* */) + (Lisp_Object obj, Lisp_Object dependency, Lisp_Object key) { mps_word_t word = XLI (obj); mps_word_t tag = word & IGC_TAG_MASK; @@ -4313,17 +4318,60 @@ DEFUN ("igc-add-extra-dependency", Figc_add_extra_dependency, struct igc_header *h = client_to_base (client); struct igc_exthdr *exthdr = igc_external_header (h); if (HASH_TABLE_P (exthdr->extra_dependency)) - Fputhash (dependency, Qt, exthdr->extra_dependency); - else if (HASH_TABLE_P (dependency) || !NILP (exthdr->extra_dependency)) + Fputhash (key, dependency, exthdr->extra_dependency); + else { Lisp_Object hash = CALLN (Fmake_hash_table); - Fputhash (dependency, Qt, hash); - if (!NILP (exthdr->extra_dependency)) - Fputhash (exthdr->extra_dependency, Qt, hash); + Fputhash (key, dependency, hash); exthdr->extra_dependency = hash; } + + return Qt; +} + +DEFUN ("igc-remove-extra-dependency", Figc_remove_extra_dependency, + Sigc_remove_extra_dependency, 2, 2, 0, doc : /* */) + (Lisp_Object obj, Lisp_Object key) +{ + mps_word_t word = XLI (obj); + mps_word_t tag = word & IGC_TAG_MASK; + mps_addr_t client = NULL; + switch (tag) + { + case Lisp_Type_Unused0: + emacs_abort (); + + case Lisp_Int0: + case Lisp_Int1: + return Qnil; + + case Lisp_Symbol: + { + ptrdiff_t off = word ^ tag; + client = (mps_addr_t) ((char *) lispsym + off); + } + break; + + case Lisp_String: + case Lisp_Vectorlike: + case Lisp_Cons: + case Lisp_Float: + client = (mps_addr_t) (word ^ tag); + break; + } + + /* Objects in the the dump have igc_headers, too. */ + if (!has_header (client, tag == Lisp_Vectorlike)) + { + return Qnil; + } + + struct igc_header *h = client_to_base (client); + struct igc_exthdr *exthdr = igc_external_header (h); + if (HASH_TABLE_P (exthdr->extra_dependency)) + Fremhash (key, exthdr->extra_dependency); else - exthdr->extra_dependency = dependency; + return Qnil; return Qt; } @@ -4756,6 +4804,7 @@ syms_of_igc (void) defsubr (&Sigc__roots); defsubr (&Sigc__collect); defsubr (&Sigc_add_extra_dependency); + defsubr (&Sigc_remove_extra_dependency); DEFSYM (Qambig, "ambig"); DEFSYM (Qexact, "exact"); Fprovide (intern_c_string ("mps"), Qnil); -- 2.45.2