From 12d78e2577eabdc36cae04bbfc08b66af777c0b7 Mon Sep 17 00:00:00 2001 From: rtoy <rtoy> Date: Wed, 16 Aug 2006 16:19:09 +0000 Subject: [PATCH] code/hash-new.lisp: o Add a new slot to the hash-table structure for GC to use for linking weak tables together. (Previously we used the weak-p slot for this. Let's make it explicit, now. Plus, this allows us to use weak-p to indicate other types of weak tables, should they be implemented.) lisp/gencgc.c: o Update defstruct appropriately. o Use the new next-weak-table slot to chain the weak tables together. o Previously we scanned the weak tables in several places in the code. However, this scanning also removed entries. I don't think we want that because later scans could make a key valid. Thus: - Change scav_hash_entries so that it doesn't remove a hash-table entry unless told to. - Add new function to scavenge weak tables without removing a weak entry. - Adjust scan_weak_tables to remove weak entries. NOTE: When building, you'll be asked twice about the hash-table structure changing size. Just select the CLOBBER-IT restart in both cases. --- code/hash-new.lisp | 14 ++++++--- lisp/gencgc.c | 77 +++++++++++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/code/hash-new.lisp b/code/hash-new.lisp index b233bc9dc..f9ea1319a 100644 --- a/code/hash-new.lisp +++ b/code/hash-new.lisp @@ -5,7 +5,7 @@ ;;; Carnegie Mellon University, and has been placed in the public domain. ;;; (ext:file-comment - "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/code/hash-new.lisp,v 1.40 2006/08/14 14:37:30 rtoy Exp $") + "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/code/hash-new.lisp,v 1.41 2006/08/16 16:19:09 rtoy Exp $") ;;; ;;; ********************************************************************** ;;; @@ -100,9 +100,15 @@ ;; This table parallels the KV table, and can be used to store the ;; hash associated with the key, saving recalculation. Could be ;; useful for EQL, and EQUAL hash tables. This table is not needed - ;; for EQ hash tables, and when present the value of #x8000000 - ;; represents EQ-based hashing on the respective Key. - (hash-vector nil :type (or null (simple-array (unsigned-byte 32) (*))))) + ;; for EQ hash tables (an is NIL in that case), and when present the + ;; value of #x8000000 represents EQ-based hashing on the respective + ;; Key. + (hash-vector nil :type (or null (simple-array (unsigned-byte 32) (*)))) + ;; + ;; This is used by GC to chain the list of weak hash tables + ;; together. It should otherwise always be NIL. + (next-weak-table nil :type (or null hash-table))) + ;;; (defun %print-hash-table (ht stream depth) (declare (ignore depth) (stream stream)) diff --git a/lisp/gencgc.c b/lisp/gencgc.c index 0378e4663..4d0b85f29 100644 --- a/lisp/gencgc.c +++ b/lisp/gencgc.c @@ -7,7 +7,7 @@ * * Douglas Crosher, 1996, 1997, 1998, 1999. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.78 2006/08/12 12:26:44 rtoy Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.79 2006/08/16 16:19:09 rtoy Exp $ * */ @@ -3595,6 +3595,7 @@ struct hash_table { lispobj index_vector; lispobj next_vector; lispobj hash_vector; /* 15 */ + lispobj next_weak_table; }; /* The size of a hash-table in Lisp objects. */ @@ -3742,7 +3743,7 @@ record_for_rehashing(struct hash_table *hash_table, int hash_index, scheduled for rehashing or removed. */ static void -scav_hash_entries(struct hash_table *hash_table, int weak) +scav_hash_entries(struct hash_table *hash_table, int weak, int removep) { unsigned kv_length; lispobj *kv_vector; @@ -3773,9 +3774,11 @@ scav_hash_entries(struct hash_table *hash_table, int weak) if (weak && !survives_gc(old_key) && index_vector[old_index] != 0 - && (hash_vector == 0 || hash_vector[i] == 0x80000000)) - free_hash_entry(hash_table, old_index, i); - else { + && (hash_vector == 0 || hash_vector[i] == 0x80000000)) { + if (removep) { + free_hash_entry(hash_table, old_index, i); + } + } else { /* If the key is EQ-hashed and moves, schedule it for rehashing. */ #if 0 if ((i < 4) && (hash_table >= (void*)0x40000000)) { @@ -3852,10 +3855,8 @@ scav_weak_entries(struct hash_table *hash_table) return scavenged; } -/* Process weak hash-tables at the end of a GC. */ - static void -scan_weak_tables(void) +scav_weak_tables(void) { lispobj table, next; int more_scavenged; @@ -3869,7 +3870,7 @@ scan_weak_tables(void) for (table = weak_hash_tables; table != NIL; table = next) { struct hash_table *ht = (struct hash_table *) PTR(table); - next = ht->weak_p; + next = ht->next_weak_table; if (scav_weak_entries(ht)) more_scavenged = 1; } @@ -3879,9 +3880,31 @@ scan_weak_tables(void) for (table = weak_hash_tables; table != NIL; table = next) { struct hash_table *ht = (struct hash_table *) PTR(table); - next = ht->weak_p; - ht->weak_p = T; - scav_hash_entries(ht, 1); + next = ht->next_weak_table; + scav_hash_entries(ht, 1, 0); + } +} + + +/* Process weak hash-tables at the end of a GC. */ + +static void +scan_weak_tables(void) +{ + lispobj table, next; + int more_scavenged; + + for (table = weak_hash_tables; table != NIL; table = next) { + struct hash_table *ht = (struct hash_table *) PTR(table); + + next = ht->next_weak_table; + /* We're done with the table, so reset the link! */ + ht->next_weak_table = NIL; + /* + * Remove the entries in the table. (This probably does too + * much work!) + */ + scav_hash_entries(ht, 1, 1); } weak_hash_tables = NIL; @@ -3955,19 +3978,17 @@ scav_hash_vector(lispobj * where, lispobj object) scavenge((lispobj *) hash_table, HASH_TABLE_SIZE); - /* Testing for T here instead of NIL automatially makes sure we - don't add the same table twice to the list of weak tables, should - this function ever be called twice for the same object. */ - - if (hash_table->weak_p == T) { - hash_table->weak_p = weak_hash_tables; -#if 0 - fprintf(stderr, " adding %p to weak_hash_tables\n", hash_table); -#endif - weak_hash_tables = hash_table_obj; - } else - scav_hash_entries(hash_table, 0); - + if (hash_table->weak_p == NIL) { + scav_hash_entries(hash_table, 0, 1); + } else if (hash_table->next_weak_table == NIL) { + /* + * Make sure we only add the table once, which means + * next_weak_table is NIL if it isn't already on the list. + */ + hash_table->next_weak_table = weak_hash_tables; + weak_hash_tables = hash_table_obj; + } + return CEILING(kv_length + 2, 2); } @@ -6002,7 +6023,7 @@ scavenge_newspace_generation(int generation) * regions are updated, so it seems to make sense to do it here as * well. */ - scan_weak_tables(); + scav_weak_tables(); /* Record all new areas now. */ @@ -6075,7 +6096,7 @@ scavenge_newspace_generation(int generation) * scavenges stuff too. */ - scan_weak_tables(); + scav_weak_tables(); /* Record all new areas now. */ record_new_objects = 2; @@ -6111,7 +6132,7 @@ scavenge_newspace_generation(int generation) * This fixes a bug with weak hash tables, reported by * Lynn Quam, cmucl-imp, 2006-07-04. */ - scan_weak_tables(); + scav_weak_tables(); /* Flush the current regions updating the tables. */ gc_alloc_update_page_tables(0, &boxed_region); -- GitLab