summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-20 07:13:05 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-20 07:13:05 -0700
commit6503c5f041f2b2791635b2bbcc7e0c9e323aeb84 (patch)
tree885a579e94016ffedd3a9a4ca22842a3daceb490
parent6f7e3aa0e70b85b8d78b8dcaaed92cd376378ece (diff)
downloadtxr-6503c5f041f2b2791635b2bbcc7e0c9e323aeb84.tar.gz
txr-6503c5f041f2b2791635b2bbcc7e0c9e323aeb84.tar.bz2
txr-6503c5f041f2b2791635b2bbcc7e0c9e323aeb84.zip
hash: fix possibly incorrect counts in weak processing.
* hash.c (do_weak_tables): Iterate to the end of each chain, not quitting early when a reachable tail is found. This has the effect that we will always count the nodes properly. Some common code is factored out of the switch also.
-rw-r--r--hash.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/hash.c b/hash.c
index b1d4f748..3746ad44 100644
--- a/hash.c
+++ b/hash.c
@@ -1215,7 +1215,7 @@ static void do_weak_tables(void)
reachable_weak_hashes = 0;
for (; h != 0; h = h->next) {
- cnum i, c;
+ cnum i, c = 0;
/* The table of a weak hash was spuriously reached by conservative GC;
it's a waste of time doing weak processing, since all keys and
values have been transitively marked as reachable; and so we
@@ -1230,11 +1230,11 @@ static void do_weak_tables(void)
case hash_weak_keys:
/* Sweep through all entries. Delete any which have keys
that are garbage. */
- for (c = 0, i = 0; i < h->modulus; i++) {
+ for (i = 0; i < h->modulus; i++) {
val *pchain = &h->table->v.vec[i];
val *iter;
- for (iter = pchain; !gc_is_reachable(*iter); ) {
+ for (iter = pchain; *iter; ) {
val entry = us_car(*iter);
if (!gc_is_reachable(entry) && !gc_is_reachable(us_car(entry))) {
*iter = us_cdr(*iter);
@@ -1248,18 +1248,15 @@ static void do_weak_tables(void)
}
}
}
- /* Garbage is gone now. Seal things by marking the vector. */
- gc_mark(h->table);
- h->count = c;
break;
case hash_weak_vals:
/* Sweep through all entries. Delete any which have values
that are garbage. */
- for (i = 0, c = 0; i < h->modulus; i++) {
+ for (i = 0; i < h->modulus; i++) {
val *pchain = &h->table->v.vec[i];
val *iter;
- for (iter = pchain; !gc_is_reachable(*iter); ) {
+ for (iter = pchain; *iter; ) {
val entry = us_car(*iter);
if (!gc_is_reachable(entry) && !gc_is_reachable(us_cdr(entry))) {
*iter = us_cdr(*iter);
@@ -1273,18 +1270,15 @@ static void do_weak_tables(void)
}
}
}
- /* Garbage is gone now. Seal things by marking the vector. */
- gc_mark(h->table);
- h->count = c;
break;
case hash_weak_both:
/* Sweep through all entries. Delete any which have keys
or values that are garbage. */
- for (i = 0, c = 0; i < h->modulus; i++) {
+ for (i = 0; i < h->modulus; i++) {
val *pchain = &h->table->v.vec[i];
val *iter;
- for (iter = pchain; !gc_is_reachable(*iter); ) {
+ for (iter = pchain; *iter; ) {
val entry = us_car(*iter);
if (!gc_is_reachable(entry) &&
(!gc_is_reachable(us_car(entry)) || !gc_is_reachable(us_cdr(entry))))
@@ -1302,11 +1296,12 @@ static void do_weak_tables(void)
}
}
}
- /* Garbage is gone now. Seal things by marking the vector. */
- gc_mark(h->table);
- h->count = c;
break;
}
+
+ /* Garbage is gone now. Seal things by marking the vector. */
+ gc_mark(h->table);
+ h->count = c;
}
/* More weak hashes were discovered during weak processing.