diff options
-rw-r--r-- | hash.c | 42 | ||||
-rw-r--r-- | txr.1 | 12 |
2 files changed, 34 insertions, 20 deletions
@@ -601,30 +601,46 @@ static void hash_mark(val hash) gc_mark(h->userdata); + if (h->count == 0) { + gc_mark(h->table); + return; + } + /* Use counts will be re-calculated by a scan of the hash iterators which are still reachable. */ h->usecount = 0; switch (h->flags) { + cnum i; + val iter; case hash_weak_none: - /* If the hash is not weak, we can simply mark the table - vector and we are done. */ gc_mark(h->table); - break; + return; case hash_weak_keys: + /* Mark values only. Don't mark the table. */ + for (i = 0; i < h->modulus; i++) { + for (iter = h->table->v.vec[i]; iter; iter = us_cdr(iter)) { + val entry = us_car(iter); + gc_mark(us_cdr(entry)); + } + } + break; case hash_weak_vals: - case hash_weak_both: - /* If the hash is weak, we don't touch it at this time, - but add it to the list of reachable weak hashes, - unless it is empty. */ - if (h->count > 0) { - h->next = reachable_weak_hashes; - reachable_weak_hashes = h; - } else { - gc_mark(h->table); - break; + /* Mark keys only. Don't mark the table. */ + for (i = 0; i < h->modulus; i++) { + for (iter = h->table->v.vec[i]; iter; iter = us_cdr(iter)) { + val entry = us_car(iter); + gc_mark(us_car(entry)); + } } + break; + case hash_weak_both: + /* mark nothing */ + break; } + + h->next = reachable_weak_hashes; + reachable_weak_hashes = h; } static struct cobj_ops hash_ops = cobj_ops_init(hash_equal_op, @@ -51061,13 +51061,11 @@ the weak references "lapse" in some way, which depends on what kind they are. Hash-table weak references lapse by entry removal. When an object used as a key in in one or more weak-key hash tables becomes unreachable, those hash entries disappear. This happens even if the values are themselves reachable. -That is what it means that. -Vice versa, when an object appearing as a value in -one or more hash-table entries in weak-value hash tables becomes unreachable, -those entries disappear, even if the keys are reachable. When a hash table has -both weak keys and weak values, then its entries are removed when either keys -or values become unreachable. In other words, both the key and value must be -reachable in order to retain the entry. +Vice versa, when an object appearing as a value in one or more weak-value hash +tables becomes unreachable, those entries disappear, even if the keys are +reachable. When a hash table has both weak keys and weak values, then its +entries are removed when either keys or values become unreachable. In other +words, both the key and value must be reachable in order to retain the entry. An open traversal of a hash table is performed by the .code maphash |