guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.0-28-g40d2a0


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.0-28-g40d2a00
Date: Wed, 23 Feb 2011 11:17:43 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=40d2a0076af69c3227bc13606aebdb5822ed7f0d

The branch, stable-2.0 has been updated
       via  40d2a0076af69c3227bc13606aebdb5822ed7f0d (commit)
      from  85bdb6ac9c8893b88c8d71a8864f019f1127eba3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 40d2a0076af69c3227bc13606aebdb5822ed7f0d
Author: Andy Wingo <address@hidden>
Date:   Wed Feb 23 11:59:38 2011 +0100

    GC dead links in weak hash tables before a possible rehash
    
    * libguile/hashtab.c (vacuum_weak_hash_table): New helper, goes through
      the entirety of a weak hash table, vacuuming dead entries.
      (scm_hash_fn_create_handle_x): If when adding to a weak hash table, we
      would trigger a rehash, vacuum the table first.  The weak_bucket_assoc
      would have only caught dead entries within one bucket.
    
      Without this patch, the following code leaks:
    
      (let lp ()
        (call-with-output-string
          (lambda (port)
            (display "foo" port)))
        (lp))

-----------------------------------------------------------------------

Summary of changes:
 libguile/hashtab.c |   34 +++++++++++++++++++++++++++++-----
 1 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/libguile/hashtab.c b/libguile/hashtab.c
index f3887c2..c703108 100644
--- a/libguile/hashtab.c
+++ b/libguile/hashtab.c
@@ -120,6 +120,26 @@ scm_fixup_weak_alist (SCM alist, size_t *removed_items)
   return result;
 }
 
+static void
+vacuum_weak_hash_table (SCM table)
+{
+  SCM buckets = SCM_HASHTABLE_VECTOR (table);
+  unsigned long k = SCM_SIMPLE_VECTOR_LENGTH (buckets);
+  size_t len = SCM_HASHTABLE_N_ITEMS (table);
+
+  while (k--)
+    {
+      size_t removed;
+      SCM alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
+      alist = scm_fixup_weak_alist (alist, &removed);
+      assert (removed <= len);
+      len -= removed;
+      SCM_SIMPLE_VECTOR_SET (buckets, k, alist);
+    }
+
+  SCM_SET_HASHTABLE_N_ITEMS (table, len);
+}
+
 
 /* Packed arguments for `do_weak_bucket_fixup'.  */
 struct t_fixup_args
@@ -651,12 +671,16 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init,
        }
       SCM_SETCDR (new_bucket, SCM_SIMPLE_VECTOR_REF (buckets, k));
       SCM_SIMPLE_VECTOR_SET (buckets, k, new_bucket);
-      /* Update element count and maybe rehash the table.  The
-         table might have too few entries here since weak hash
-         tables used with the hashx_* functions can not be
-         rehashed after GC.
-      */
       SCM_HASHTABLE_INCREMENT (table);
+
+      /* Maybe rehash the table.  If it's a weak table, pump all of the
+         buckets first to remove stale links.  If the weak table is of
+         the kind that gets lots of insertions of short-lived values, we
+         might never need to actually rehash.  */
+      if (SCM_HASHTABLE_WEAK_P (table)
+          && SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
+        vacuum_weak_hash_table (table);
+          
       if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table)
           || SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
         scm_i_rehash (table, hash_fn, closure, FUNC_NAME);


hooks/post-receive
-- 
GNU Guile



reply via email to

[Prev in Thread] Current Thread [Next in Thread]