guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] GNU Guile branch, master, updated. v2.1.0-30-g633f3a1


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. v2.1.0-30-g633f3a1
Date: Mon, 24 Oct 2011 10:59:31 +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=633f3a18b7c6804b75ecd8ae94cf6cf82c9bcbed

The branch, master has been updated
       via  633f3a18b7c6804b75ecd8ae94cf6cf82c9bcbed (commit)
       via  a141db8604ecca8a4f4c210cd680b41e337c689a (commit)
       via  c4e83f74c2f518d8c25959c6e7bb2b36e7058d01 (commit)
       via  203a92b67b6a6c64c9e9f33d99c48f4699ed30e2 (commit)
       via  54a9b981a4e64dd58e1d3dec474b8c397c30c1c9 (commit)
       via  7005c60fcbb8053d58dde579d8eef40bfe4d670f (commit)
      from  2721f9182da74cf98426cc335f3f39c265cc412d (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 633f3a18b7c6804b75ecd8ae94cf6cf82c9bcbed
Author: Andy Wingo <address@hidden>
Date:   Mon Oct 24 10:55:46 2011 +0200

    remove mutex in make-object-property
    
    * module/ice-9/boot-9.scm (make-object-property): Remove the mutex; weak
      tables are now threadsafe.

commit a141db8604ecca8a4f4c210cd680b41e337c689a
Author: Andy Wingo <address@hidden>
Date:   Mon Oct 24 10:52:55 2011 +0200

    remove weak pairs, rewrite weak vectors
    
    * libguile/weak-vector.c:
    * libguile/weak-vector.h: Renamed from weaks.[ch].  Remove weak pairs.
      They were not safe to access with `car' and `cdr'.  Remove weak alist
      vectors, as we have weak tables and sets.  Reimplement weak vectors,
      moving the implementation here.
    
    * libguile/vectors.c:
    * libguile/vectors.h: Remove the extra header word.  Use
      scm_c_weak_vector_ref / scm_c_weak_vector_set_x to access weak
      vectors.
    
    * libguile/snarf.h: Remove the extra header word in vectors.
    
    * libguile/threads.c (do_thread_exit, fat_mutex_lock, fat_mutex_unlock):
      Instead of weak pairs, store thread-owned mutexes in a list of
      one-element weak vectors.
    
    * libguile/guardians.c (finalize_guarded): Similarly, store object
      guardians in a list of one-element weak vectors.
    
    * libguile/modules.c (scm_module_reverse_lookup): We no longer need to
      handle the case of weak references.
    
    * libguile/print.c (iprin1): Use the standard vector accessor to print
      vectors.
    
    * libguile.h:
    * libguile/Makefile.am:
    * libguile/gc-malloc.c:
    * libguile/gc.c:
    * libguile/goops.c:
    * libguile/init.c:
    * libguile/objprop.c:
    * libguile/struct.c: Update includes.
    
    * module/ice-9/weak-vector.scm: Load weak vector definitions using an
      extension instead of %init-weaks-builtins.
    
    * test-suite/tests/weaks.test: Use the make-...-hash-table names instead
      of the old alist vector names.

commit c4e83f74c2f518d8c25959c6e7bb2b36e7058d01
Author: Andy Wingo <address@hidden>
Date:   Mon Oct 24 08:28:06 2011 +0200

    remove a stale comment
    
    * module/system/foreign.scm (define-wrapped-pointer-type): Remove stale
      comment.

commit 203a92b67b6a6c64c9e9f33d99c48f4699ed30e2
Author: Andy Wingo <address@hidden>
Date:   Sun Oct 23 23:38:51 2011 +0200

    convert internal weak hash table users to use the weak table api
    
    The weak table API isn't public yet.  It could be after some review.
    But we can go ahead and use it now internally.
    
    * libguile/foreign.c:
    * libguile/goops.c:
    * libguile/objprop.c:
    * libguile/procprop.c:
    * libguile/smob.c:
    * libguile/srcprop.c: Update weak table users to new API.  No locking
      needed!

commit 54a9b981a4e64dd58e1d3dec474b8c397c30c1c9
Author: Andy Wingo <address@hidden>
Date:   Mon Oct 24 07:57:17 2011 +0200

    reimplement hashtab.c's weak hash tables in terms of weak-table.c
    
    * libguile/hashtab.c:
    * libguile/hashtab.h: Reimplement the weak hash table implementation in
      terms of weak tables.  All is well except for the horrific hack for
      hashx tables.
    
    * libguile/weak-table.h:
    * libguile/weak-table.c (scm_make_weak_key_hash_table)
      (scm_make_weak_value_hash_table, scm_make_doubly_weak_hash_table)
      (scm_weak_key_hash_table_p, scm_weak_value_hash_table_p)
      (scm_doubly_weak_hash_table_p): Move these definitions here.

commit 7005c60fcbb8053d58dde579d8eef40bfe4d670f
Author: Andy Wingo <address@hidden>
Date:   Sun Oct 23 23:23:47 2011 +0200

    add weak table implementation
    
    * libguile/weak-table.c:
    * libguile/weak-table.h: New files, implementing open-addressed weak
      hash tables, similar to the implementation of weak sets.  This will
      let us remove weak pairs.
    
    * libguile.h:
    * libguile/Makefile.am:
    * libguile/evalext.c:
    * libguile/gc.c:
    * libguile/init.c:
    * libguile/print.c:
    * libguile/tags.h: Update all the pieces for the new files and tc7.

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

Summary of changes:
 libguile.h                               |    3 +-
 libguile/Makefile.am                     |   12 +-
 libguile/evalext.c                       |    1 +
 libguile/foreign.c                       |    7 +-
 libguile/gc-malloc.c                     |    1 -
 libguile/gc.c                            |    3 +-
 libguile/goops.c                         |   16 +-
 libguile/guardians.c                     |   16 +-
 libguile/hashtab.c                       |  704 ++++---------------
 libguile/hashtab.h                       |   32 +-
 libguile/init.c                          |    8 +-
 libguile/modules.c                       |   12 +-
 libguile/objprop.c                       |   24 +-
 libguile/print.c                         |   34 +-
 libguile/procprop.c                      |   21 +-
 libguile/smob.c                          |   11 +-
 libguile/snarf.h                         |    9 +-
 libguile/srcprop.c                       |   66 +-
 libguile/struct.c                        |    1 -
 libguile/tags.h                          |    2 +-
 libguile/threads.c                       |   33 +-
 libguile/vectors.c                       |  179 +----
 libguile/vectors.h                       |   21 +-
 libguile/weak-table.c                    | 1134 ++++++++++++++++++++++++++++++
 libguile/weak-table.h                    |   94 +++
 libguile/weak-vector.c                   |  207 ++++++
 libguile/{extensions.h => weak-vector.h} |   22 +-
 libguile/weaks.c                         |  294 --------
 libguile/weaks.h                         |  101 ---
 module/ice-9/boot-9.scm                  |   12 +-
 module/ice-9/weak-vector.scm             |   15 +-
 module/system/foreign.scm                |    4 -
 test-suite/tests/weaks.test              |   24 +-
 33 files changed, 1767 insertions(+), 1356 deletions(-)
 create mode 100644 libguile/weak-table.c
 create mode 100644 libguile/weak-table.h
 create mode 100644 libguile/weak-vector.c
 copy libguile/{extensions.h => weak-vector.h} (60%)
 delete mode 100644 libguile/weaks.c
 delete mode 100644 libguile/weaks.h

diff --git a/libguile.h b/libguile.h
index 24a3c96..7ac98a5 100644
--- a/libguile.h
+++ b/libguile.h
@@ -116,7 +116,8 @@ extern "C" {
 #include "libguile/version.h"
 #include "libguile/vports.h"
 #include "libguile/weak-set.h"
-#include "libguile/weaks.h"
+#include "libguile/weak-table.h"
+#include "libguile/weak-vector.h"
 #include "libguile/backtrace.h"
 #include "libguile/debug.h"
 #include "libguile/stacks.h"
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 6f78d06..502ae56 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -219,7 +219,8 @@ address@hidden@_la_SOURCES =                                
\
        vm.c                                    \
        vports.c                                \
        weak-set.c                              \
-       weaks.c
+       weak-table.c                            \
+       weak-vector.c
 
 DOT_X_FILES =                                  \
        alist.x                                 \
@@ -316,7 +317,8 @@ DOT_X_FILES =                                       \
        version.x                               \
        vports.x                                \
        weak-set.x                              \
-       weaks.x
+       weak-table.x                            \
+       weak-vector.x
 
 # vm-related snarfs
 DOT_X_FILES += frames.x instructions.x objcodes.x programs.x vm.x
@@ -418,7 +420,8 @@ DOT_DOC_FILES =                             \
        version.doc                             \
        vports.doc                              \
        weak-set.doc                            \
-       weaks.doc
+       weak-table.doc                          \
+       weak-vector.doc
 
 EXTRA_DOT_DOC_FILES = @EXTRA_DOT_DOC_FILES@
 
@@ -621,7 +624,8 @@ modinclude_HEADERS =                                \
        vm.h                                    \
        vports.h                                \
        weak-set.h                              \
-       weaks.h
+       weak-table.h                            \
+       weak-vector.h
 
 nodist_modinclude_HEADERS = version.h scmconfig.h
 
diff --git a/libguile/evalext.c b/libguile/evalext.c
index 83b70f1..779c63d 100644
--- a/libguile/evalext.c
+++ b/libguile/evalext.c
@@ -77,6 +77,7 @@ SCM_DEFINE (scm_self_evaluating_p, "self-evaluating?", 1, 0, 
0,
        case scm_tc7_pointer:
        case scm_tc7_hashtable:
        case scm_tc7_weak_set:
+       case scm_tc7_weak_table:
        case scm_tc7_fluid:
        case scm_tc7_dynamic_state:
         case scm_tc7_frame:
diff --git a/libguile/foreign.c b/libguile/foreign.c
index e82a8c5..2a11fb0 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -87,15 +87,12 @@ static SCM cif_to_procedure (SCM cif, SCM func_ptr);
 
 
 static SCM pointer_weak_refs = SCM_BOOL_F;
-static scm_i_pthread_mutex_t weak_refs_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 
 static void
 register_weak_reference (SCM from, SCM to)
 {
-  scm_i_pthread_mutex_lock (&weak_refs_lock);
-  scm_hashq_set_x (pointer_weak_refs, from, to);
-  scm_i_pthread_mutex_unlock (&weak_refs_lock);
+  scm_weak_table_putq_x (pointer_weak_refs, from, to);
 }
 
 static void
@@ -1272,7 +1269,7 @@ scm_register_foreign (void)
                             "scm_init_foreign",
                             (scm_t_extension_init_func)scm_init_foreign,
                             NULL);
-  pointer_weak_refs = scm_make_weak_key_hash_table (SCM_UNDEFINED);
+  pointer_weak_refs = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
 }
 
 /*
diff --git a/libguile/gc-malloc.c b/libguile/gc-malloc.c
index 839154a..d02d847 100644
--- a/libguile/gc-malloc.c
+++ b/libguile/gc-malloc.c
@@ -43,7 +43,6 @@ extern unsigned long * 
__libc_ia64_register_backing_store_base;
 #include "libguile/root.h"
 #include "libguile/strings.h"
 #include "libguile/vectors.h"
-#include "libguile/weaks.h"
 #include "libguile/hashtab.h"
 #include "libguile/tags.h"
 
diff --git a/libguile/gc.c b/libguile/gc.c
index 42b29fb..696e321 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -45,7 +45,6 @@ extern unsigned long * 
__libc_ia64_register_backing_store_base;
 #include "libguile/root.h"
 #include "libguile/strings.h"
 #include "libguile/vectors.h"
-#include "libguile/weaks.h"
 #include "libguile/hashtab.h"
 #include "libguile/tags.h"
 
@@ -753,6 +752,8 @@ scm_i_tag_name (scm_t_bits tag)
       return "hashtable";
     case scm_tc7_weak_set:
       return "weak-set";
+    case scm_tc7_weak_table:
+      return "weak-table";
     case scm_tc7_fluid:
       return "fluid";
     case scm_tc7_dynamic_state:
diff --git a/libguile/goops.c b/libguile/goops.c
index f0a4315..4b09f33 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -53,7 +53,6 @@
 #include "libguile/strings.h"
 #include "libguile/strports.h"
 #include "libguile/vectors.h"
-#include "libguile/weaks.h"
 #include "libguile/vm.h"
 
 #include "libguile/validate.h"
@@ -163,7 +162,6 @@ static SCM class_bytevector;
 static SCM class_uvec;
 
 static SCM vtable_class_map = SCM_BOOL_F;
-static scm_i_pthread_mutex_t vtable_class_map_lock = 
SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 /* Port classes.  Allocate 3 times the maximum number of port types so that
    input ports, output ports, and in/out ports can be stored at different
@@ -191,17 +189,15 @@ scm_i_define_class_for_vtable (SCM vtable)
 {
   SCM class;
 
-  scm_i_pthread_mutex_lock (&vtable_class_map_lock);
-
+  scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
   if (scm_is_false (vtable_class_map))
-    vtable_class_map = scm_make_weak_key_hash_table (SCM_UNDEFINED);
+    vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
+  scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
   
   if (scm_is_false (scm_struct_vtable_p (vtable)))
     abort ();
 
-  class = scm_hashq_ref (vtable_class_map, vtable, SCM_BOOL_F);
-  
-  scm_i_pthread_mutex_unlock (&vtable_class_map_lock);
+  class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
 
   if (scm_is_false (class))
     {
@@ -220,9 +216,7 @@ scm_i_define_class_for_vtable (SCM vtable)
 
       /* Don't worry about races.  This only happens when creating a
          vtable, which happens by definition in one thread.  */
-      scm_i_pthread_mutex_lock (&vtable_class_map_lock);
-      scm_hashq_set_x (vtable_class_map, vtable, class);
-      scm_i_pthread_mutex_unlock (&vtable_class_map_lock);
+      scm_weak_table_putq_x (vtable_class_map, vtable, class);
     }
 
   return class;
diff --git a/libguile/guardians.c b/libguile/guardians.c
index 81313df..076df00 100644
--- a/libguile/guardians.c
+++ b/libguile/guardians.c
@@ -57,7 +57,6 @@
 #include "libguile/validate.h"
 #include "libguile/root.h"
 #include "libguile/hashtab.h"
-#include "libguile/weaks.h"
 #include "libguile/deprecation.h"
 #include "libguile/eval.h"
 
@@ -131,9 +130,12 @@ finalize_guarded (GC_PTR ptr, GC_PTR finalizer_data)
        guardian_list = SCM_CDR (guardian_list))
     {
       SCM zombies;
+      SCM guardian;
       t_guardian *g;
 
-      if (SCM_WEAK_PAIR_CAR_DELETED_P (guardian_list))
+      guardian = scm_c_weak_vector_ref (scm_car (guardian_list), 0);
+      
+      if (scm_is_false (guardian))
        {
          /* The guardian itself vanished in the meantime.  */
 #ifdef DEBUG_GUARDIANS
@@ -142,7 +144,7 @@ finalize_guarded (GC_PTR ptr, GC_PTR finalizer_data)
          continue;
        }
 
-      g = GUARDIAN_DATA (SCM_CAR (guardian_list));
+      g = GUARDIAN_DATA (guardian);
       if (g->live == 0)
        abort ();
 
@@ -209,9 +211,11 @@ scm_i_guard (SCM guardian, SCM obj)
 
       g->live++;
 
-      /* Note: GUARDIANS_FOR_OBJ is a weak list so that a guardian can be
-        collected before the objects it guards (see `guardians.test').  */
-      guardians_for_obj = scm_weak_car_pair (guardian, SCM_EOL);
+      /* Note: GUARDIANS_FOR_OBJ holds weak references to guardians so
+        that a guardian can be collected before the objects it guards
+        (see `guardians.test').  */
+      guardians_for_obj = scm_cons (scm_make_weak_vector (SCM_INUM1, guardian),
+                                    SCM_EOL);
       finalizer_data = scm_cons (SCM_BOOL_F, guardians_for_obj);
 
       GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (obj), finalize_guarded,
diff --git a/libguile/hashtab.c b/libguile/hashtab.c
index c4f2b5e..1f1f69c 100644
--- a/libguile/hashtab.c
+++ b/libguile/hashtab.c
@@ -53,9 +53,6 @@
  * The implementation stores the upper and lower number of items which
  * trigger a resize in the hashtable object.
  *
- * Weak hash tables use weak pairs in the bucket lists rather than
- * normal pairs.
- *
  * Possible hash table sizes (primes) are stored in the array
  * hashtable_size.
  */
@@ -75,201 +72,8 @@ static unsigned long hashtable_size[] = {
 
 static char *s_hashtable = "hashtable";
 
-
-
-/* Helper functions and macros to deal with weak pairs.
-
-   Weak pairs need to be accessed very carefully since their components can
-   be nullified by the GC when the object they refer to becomes unreachable.
-   Hence the macros and functions below that detect such weak pairs within
-   buckets and remove them.  */
-
-
-/* Remove nullified weak pairs from ALIST such that the result contains only
-   valid pairs.  Set REMOVED_ITEMS to the number of pairs that have been
-   deleted.  */
 static SCM
-scm_fixup_weak_alist (SCM alist, size_t *removed_items)
-{
-  SCM result;
-  SCM prev = SCM_EOL;
-
-  *removed_items = 0;
-  for (result = alist;
-       scm_is_pair (alist);
-       alist = SCM_CDR (alist))
-    {
-      SCM pair = SCM_CAR (alist);
-
-      if (SCM_WEAK_PAIR_DELETED_P (pair))
-       {
-         /* Remove from ALIST weak pair PAIR whose car/cdr has been
-            nullified by the GC.  */
-         if (scm_is_null (prev))
-           result = SCM_CDR (alist);
-         else
-           SCM_SETCDR (prev, SCM_CDR (alist));
-
-         (*removed_items)++;
-
-         /* Leave PREV unchanged.  */
-       }
-      else
-       prev = alist;
-    }
-
-  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
-{
-  SCM bucket;
-  SCM *bucket_copy;
-  size_t removed_items;
-};
-
-static void *
-do_weak_bucket_fixup (void *data)
-{
-  struct t_fixup_args *args;
-  SCM pair, *copy;
-
-  args = (struct t_fixup_args *) data;
-
-  args->bucket = scm_fixup_weak_alist (args->bucket, &args->removed_items);
-
-  for (pair = args->bucket, copy = args->bucket_copy;
-       scm_is_pair (pair);
-       pair = SCM_CDR (pair), copy += 2)
-    {
-      /* At this point, all weak pairs have been removed.  */
-      assert (!SCM_WEAK_PAIR_DELETED_P (SCM_CAR (pair)));
-
-      /* Copy the key and value.  */
-      copy[0] = SCM_CAAR (pair);
-      copy[1] = SCM_CDAR (pair);
-    }
-
-  return args;
-}
-
-/* Lookup OBJECT in weak hash table TABLE using ASSOC.  OBJECT is searched
-   for in the alist that is the BUCKET_INDEXth element of BUCKETS.
-   Optionally update TABLE and rehash it.  */
-static SCM
-weak_bucket_assoc (SCM table, SCM buckets, size_t bucket_index,
-                  scm_t_hash_fn hash_fn,
-                  scm_t_assoc_fn assoc, SCM object, void *closure)
-{
-  SCM result;
-  SCM bucket, *strong_refs;
-  struct t_fixup_args args;
-
-  bucket = SCM_SIMPLE_VECTOR_REF (buckets, bucket_index);
-
-  /* Prepare STRONG_REFS as an array large enough to hold all the keys
-     and values in BUCKET.  */
-  strong_refs = alloca (scm_ilength (bucket) * 2 * sizeof (SCM));
-
-  args.bucket = bucket;
-  args.bucket_copy = strong_refs;
-
-  /* Fixup BUCKET.  Do that with the allocation lock held to avoid
-     seeing disappearing links pointing to objects that have already
-     been reclaimed (this happens when the disappearing links that point
-     to it haven't yet been cleared.)
-
-     The `do_weak_bucket_fixup' call populates STRONG_REFS with a copy
-     of BUCKET's entries after it's been fixed up.  Thus, all the
-     entries kept in BUCKET are still reachable when ASSOC sees
-     them.  */
-  GC_call_with_alloc_lock (do_weak_bucket_fixup, &args);
-
-  bucket = args.bucket;
-  SCM_SIMPLE_VECTOR_SET (buckets, bucket_index, bucket);
-
-  result = assoc (object, bucket, closure);
-
-  /* If we got a result, it should not have NULL fields.  */
-  if (scm_is_pair (result) && SCM_WEAK_PAIR_DELETED_P (result))
-    abort ();
-
-  scm_remember_upto_here_1 (strong_refs);
-
-  if (args.removed_items > 0)
-    {
-      /* Update TABLE's item count and optionally trigger a rehash.  */
-      size_t remaining;
-
-      assert (SCM_HASHTABLE_N_ITEMS (table) >= args.removed_items);
-
-      remaining = SCM_HASHTABLE_N_ITEMS (table) - args.removed_items;
-      SCM_SET_HASHTABLE_N_ITEMS (table, remaining);
-
-      if (remaining < SCM_HASHTABLE_LOWER (table))
-       scm_i_rehash (table, hash_fn, closure, "weak_bucket_assoc");
-    }
-
-  return result;
-}
-
-
-/* Packed arguments for `weak_bucket_assoc_by_hash'.  */
-struct assoc_by_hash_data
-{
-  SCM alist;
-  SCM ret;
-  scm_t_hash_predicate_fn predicate;
-  void *closure;
-};
-
-/* See scm_hash_fn_get_handle_by_hash below.  */
-static void*
-weak_bucket_assoc_by_hash (void *args)
-{
-  struct assoc_by_hash_data *data = args;
-  SCM alist = data->alist;
-
-  for (; scm_is_pair (alist); alist = SCM_CDR (alist))
-    {
-      SCM pair = SCM_CAR (alist);
-      
-      if (!SCM_WEAK_PAIR_DELETED_P (pair)
-          && data->predicate (SCM_CAR (pair), data->closure))
-        {
-          data->ret = pair;
-          break;
-        }
-    }
-  return args;
-}
-        
-
-
-static SCM
-make_hash_table (int flags, unsigned long k, const char *func_name) 
+make_hash_table (unsigned long k, const char *func_name) 
 {
   SCM vector;
   scm_t_hashtable *t;
@@ -278,9 +82,6 @@ make_hash_table (int flags, unsigned long k, const char 
*func_name)
     ++i;
   n = hashtable_size[i];
 
-  /* In both cases, i.e., regardless of whether we are creating a weak hash
-     table, we return a non-weak vector.  This is because the vector itself
-     is not weak in the case of a weak hash table: the alist pairs are.  */
   vector = scm_c_make_vector (n, SCM_EOL);
 
   t = scm_gc_malloc_pointerless (sizeof (*t), s_hashtable);
@@ -288,8 +89,6 @@ make_hash_table (int flags, unsigned long k, const char 
*func_name)
   t->n_items = 0;
   t->lower = 0;
   t->upper = 9 * n / 10;
-  t->flags = flags;
-  t->hash_fn = NULL;
 
   /* FIXME: we just need two words of storage, not three */
   return scm_double_cell (scm_tc7_hashtable, SCM_UNPACK (vector),
@@ -322,13 +121,6 @@ scm_i_rehash (SCM table,
       if (i >= HASHTABLE_SIZE_N)
        /* don't rehash */
        return;
-
-      /* Remember HASH_FN for rehash_after_gc, but only when CLOSURE
-        is not needed since CLOSURE can not be guaranteed to be valid
-        after this function returns.
-      */
-      if (closure == NULL)
-       SCM_HASHTABLE (table)->hash_fn = hash_fn;
     }
   SCM_HASHTABLE (table)->size_index = i;
   
@@ -342,13 +134,6 @@ scm_i_rehash (SCM table,
 
   new_buckets = scm_c_make_vector (new_size, SCM_EOL);
 
-  /* When this is a weak hashtable, running the GC might change it.
-     We need to cope with this while rehashing its elements.  We do
-     this by first installing the new, empty bucket vector.  Then we
-     remove the elements from the old bucket vector and insert them
-     into the new one.
-  */
-
   SCM_SET_HASHTABLE_VECTOR (table, new_buckets);
   SCM_SET_HASHTABLE_N_ITEMS (table, 0);
 
@@ -368,10 +153,6 @@ scm_i_rehash (SCM table,
          handle = SCM_CAR (cell);
          ls = SCM_CDR (ls);
 
-         if (SCM_WEAK_PAIR_DELETED_P (handle))
-           /* HANDLE is a nullified weak pair: skip it.  */
-           continue;
-
          h = hash_fn (SCM_CAR (handle), new_size, closure);
          if (h >= new_size)
            scm_out_of_range (func_name, scm_from_ulong (h));
@@ -386,14 +167,7 @@ scm_i_rehash (SCM table,
 void
 scm_i_hashtable_print (SCM exp, SCM port, scm_print_state *pstate)
 {
-  scm_puts ("#<", port);
-  if (SCM_HASHTABLE_WEAK_KEY_P (exp))
-    scm_puts ("weak-key-", port);
-  else if (SCM_HASHTABLE_WEAK_VALUE_P (exp))
-    scm_puts ("weak-value-", port);
-  else if (SCM_HASHTABLE_DOUBLY_WEAK_P (exp))
-    scm_puts ("doubly-weak-", port);
-  scm_puts ("hash-table ", port);
+  scm_puts ("#<hash-table ", port);
   scm_uintprint (SCM_HASHTABLE_N_ITEMS (exp), 10, port);
   scm_putc ('/', port);
   scm_uintprint (SCM_SIMPLE_VECTOR_LENGTH (SCM_HASHTABLE_VECTOR (exp)),
@@ -405,7 +179,7 @@ scm_i_hashtable_print (SCM exp, SCM port, scm_print_state 
*pstate)
 SCM
 scm_c_make_hash_table (unsigned long k)
 {
-  return make_hash_table (0, k, "scm_c_make_hash_table");
+  return make_hash_table (k, "scm_c_make_hash_table");
 }
 
 SCM_DEFINE (scm_make_hash_table, "make-hash-table", 0, 1, 0,
@@ -413,171 +187,18 @@ SCM_DEFINE (scm_make_hash_table, "make-hash-table", 0, 
1, 0,
            "Make a new abstract hash table object with minimum number of 
buckets @var{n}\n")
 #define FUNC_NAME s_scm_make_hash_table
 {
-  if (SCM_UNBNDP (n))
-    return make_hash_table (0, 0, FUNC_NAME);
-  else
-    return make_hash_table (0, scm_to_ulong (n), FUNC_NAME);
-}
-#undef FUNC_NAME
-
-/* The before-gc C hook only runs if GC_set_start_callback is available,
-   so if not, fall back on a finalizer-based implementation.  */
-static int
-weak_gc_callback (void **weak)
-{
-  void *val = weak[0];
-  void (*callback) (SCM) = weak[1];
-  
-  if (!val)
-    return 0;
-  
-  callback (PTR2SCM (val));
-
-  return 1;
-}
-
-#ifdef HAVE_GC_SET_START_CALLBACK
-static void*
-weak_gc_hook (void *hook_data, void *fn_data, void *data)
-{
-  if (!weak_gc_callback (fn_data))
-    scm_c_hook_remove (&scm_before_gc_c_hook, weak_gc_hook, fn_data);
-
-  return NULL;
-}
-#else
-static void
-weak_gc_finalizer (void *ptr, void *data)
-{
-  if (weak_gc_callback (ptr))
-    GC_REGISTER_FINALIZER_NO_ORDER (ptr, weak_gc_finalizer, data, NULL, NULL);
-}
-#endif
-
-static void
-scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM))
-{
-  void **weak = GC_MALLOC_ATOMIC (sizeof (void*) * 2);
-
-  weak[0] = SCM2PTR (obj);
-  weak[1] = (void*)callback;
-  GC_GENERAL_REGISTER_DISAPPEARING_LINK (weak, SCM2PTR (obj));
-
-#ifdef HAVE_GC_SET_START_CALLBACK
-  scm_c_hook_add (&scm_before_gc_c_hook, weak_gc_hook, weak, 0);
-#else
-  GC_REGISTER_FINALIZER_NO_ORDER (weak, weak_gc_finalizer, NULL, NULL, NULL);
-#endif
-}
-
-SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0, 
-           (SCM n),
-           "@deffnx {Scheme Procedure} make-weak-value-hash-table size\n"
-           "@deffnx {Scheme Procedure} make-doubly-weak-hash-table size\n"
-           "Return a weak hash table with @var{size} buckets.\n"
-           "\n"
-           "You can modify weak hash tables in exactly the same way you\n"
-           "would modify regular hash tables. (@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_weak_key_hash_table
-{
-  SCM ret;
-
-  if (SCM_UNBNDP (n))
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR, 0, FUNC_NAME);
-  else
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR,
-                           scm_to_ulong (n), FUNC_NAME);
-
-  scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
-
-  return ret;
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 0, 
1, 0, 
-            (SCM n),
-           "Return a hash table with weak values with @var{size} buckets.\n"
-           "(@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_weak_value_hash_table
-{
-  SCM ret;
-
-  if (SCM_UNBNDP (n))
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CDR, 0, FUNC_NAME);
-  else
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CDR,
-                           scm_to_ulong (n), FUNC_NAME);
-
-  scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
-
-  return ret;
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 
0, 0, 
-            (SCM n),
-           "Return a hash table with weak keys and values with @var{size}\n"
-           "buckets.  (@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_doubly_weak_hash_table
-{
-  SCM ret;
-
-  if (SCM_UNBNDP (n))
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
-                           0, FUNC_NAME);
-  else
-    ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
-                           scm_to_ulong (n), FUNC_NAME);
-
-  scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
-
-  return ret;
+  return make_hash_table (SCM_UNBNDP (n) ? 0 : scm_to_ulong (n), FUNC_NAME);
 }
 #undef FUNC_NAME
 
+#define SCM_WEAK_TABLE_P(x) (scm_is_true (scm_weak_table_p (x)))
 
 SCM_DEFINE (scm_hash_table_p, "hash-table?", 1, 0, 0, 
             (SCM obj),
            "Return @code{#t} if @var{obj} is an abstract hash table object.")
 #define FUNC_NAME s_scm_hash_table_p
 {
-  return scm_from_bool (SCM_HASHTABLE_P (obj));
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_weak_key_hash_table_p, "weak-key-hash-table?", 1, 0, 0, 
-           (SCM obj),
-           "@deffnx {Scheme Procedure} weak-value-hash-table? obj\n"
-           "@deffnx {Scheme Procedure} doubly-weak-hash-table? obj\n"
-           "Return @code{#t} if @var{obj} is the specified weak hash\n"
-           "table. Note that a doubly weak hash table is neither a weak key\n"
-           "nor a weak value hash table.")
-#define FUNC_NAME s_scm_weak_key_hash_table_p
-{
-  return scm_from_bool (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_WEAK_KEY_P 
(obj));
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_weak_value_hash_table_p, "weak-value-hash-table?", 1, 0, 0, 
-            (SCM obj),
-           "Return @code{#t} if @var{obj} is a weak value hash table.")
-#define FUNC_NAME s_scm_weak_value_hash_table_p
-{
-  return scm_from_bool (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_WEAK_VALUE_P 
(obj));
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_doubly_weak_hash_table_p, "doubly-weak-hash-table?", 1, 0, 0, 
-            (SCM obj),
-           "Return @code{#t} if @var{obj} is a doubly weak hash table.")
-#define FUNC_NAME s_scm_doubly_weak_hash_table_p
-{
-  return scm_from_bool (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_DOUBLY_WEAK_P 
(obj));
+  return scm_from_bool (SCM_HASHTABLE_P (obj) || SCM_WEAK_TABLE_P (obj));
 }
 #undef FUNC_NAME
 
@@ -602,69 +223,7 @@ scm_hash_fn_get_handle (SCM table, SCM obj,
   if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
     scm_out_of_range (FUNC_NAME, scm_from_ulong (k));
 
-  if (SCM_HASHTABLE_WEAK_P (table))
-    h = weak_bucket_assoc (table, buckets, k, hash_fn,
-                          assoc_fn, obj, closure);
-  else
-    h = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
-
-  return h;
-}
-#undef FUNC_NAME
-
-
-/* This procedure implements three optimizations, with respect to the
-   raw get_handle():
-
-   1. For weak tables, it's assumed that calling the predicate in the
-      allocation lock is safe. In practice this means that the predicate
-      cannot call arbitrary scheme functions. 
-
-   2. We don't check for overflow / underflow and rehash.
-
-   3. We don't actually have to allocate a key -- instead we get the
-      hash value directly. This is useful for, for example, looking up
-      strings in the symbol table.
- */
-SCM
-scm_hash_fn_get_handle_by_hash (SCM table, unsigned long raw_hash,
-                                scm_t_hash_predicate_fn predicate_fn,
-                                void *closure)
-#define FUNC_NAME "scm_hash_fn_ref_by_hash"
-{
-  unsigned long k;
-  SCM buckets, alist, h = SCM_BOOL_F;
-
-  SCM_VALIDATE_HASHTABLE (SCM_ARG1, table);
-  buckets = SCM_HASHTABLE_VECTOR (table);
-
-  if (SCM_SIMPLE_VECTOR_LENGTH (buckets) == 0)
-    return SCM_BOOL_F;
-
-  k = raw_hash % SCM_SIMPLE_VECTOR_LENGTH (buckets);
-  alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
-
-  if (SCM_HASHTABLE_WEAK_P (table))
-    {
-      struct assoc_by_hash_data args;
-
-      args.alist = alist;
-      args.ret = SCM_BOOL_F;
-      args.predicate = predicate_fn;
-      args.closure = closure;
-      GC_call_with_alloc_lock (weak_bucket_assoc_by_hash, &args);
-      h = args.ret;
-    }
-  else
-    for (; scm_is_pair (alist); alist = SCM_CDR (alist))
-      {
-        SCM pair = SCM_CAR (alist);
-        if (predicate_fn (SCM_CAR (pair), closure))
-          {
-            h = pair;
-            break;
-          }
-      }
+  h = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
 
   return h;
 }
@@ -690,11 +249,7 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init,
   if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
     scm_out_of_range ("hash_fn_create_handle_x", scm_from_ulong (k));
 
-  if (SCM_HASHTABLE_WEAK_P (table))
-    it = weak_bucket_assoc (table, buckets, k, hash_fn,
-                           assoc_fn, obj, closure);
-  else
-    it = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
+  it = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
 
   if (scm_is_pair (it))
     return it;
@@ -702,29 +257,9 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init,
     scm_wrong_type_arg_msg (NULL, 0, it, "a pair");
   else
     {
-      /* When this is a weak hashtable, running the GC can change it.
-        Thus, we must allocate the new cells first and can only then
-        access BUCKETS.  Also, we need to fetch the bucket vector
-        again since the hashtable might have been rehashed.  This
-        necessitates a new hash value as well.
-      */
       SCM handle, new_bucket;
 
-      if (SCM_HASHTABLE_WEAK_P (table))
-       {
-         /* FIXME: We don't support weak alist vectors.  */
-         /* Use a weak cell.  */
-         if (SCM_HASHTABLE_DOUBLY_WEAK_P (table))
-           handle = scm_doubly_weak_pair (obj, init);
-         else if (SCM_HASHTABLE_WEAK_KEY_P (table))
-           handle = scm_weak_car_pair (obj, init);
-         else
-           handle = scm_weak_cdr_pair (obj, init);
-       }
-      else
-       /* Use a regular, non-weak cell.  */
-       handle = scm_cons (obj, init);
-
+      handle = scm_cons (obj, init);
       new_bucket = scm_cons (handle, SCM_EOL);
 
       if (!scm_is_eq (SCM_HASHTABLE_VECTOR (table), buckets))
@@ -760,36 +295,6 @@ scm_hash_fn_ref (SCM table, SCM obj, SCM dflt,
     return dflt;
 }
 
-struct weak_cdr_data
-{
-  SCM pair;
-  SCM cdr;
-};
-
-static void*
-get_weak_cdr (void *data)
-{
-  struct weak_cdr_data *d = data;
-
-  if (SCM_WEAK_PAIR_CDR_DELETED_P (d->pair))
-    d->cdr = SCM_BOOL_F;
-  else
-    d->cdr = SCM_CDR (d->pair);
-
-  return NULL;
-}
-
-static SCM
-weak_pair_cdr (SCM x)
-{
-  struct weak_cdr_data data;
-
-  data.pair = x;
-  GC_call_with_alloc_lock (get_weak_cdr, &data);
-
-  return data.cdr;
-}
-
 SCM
 scm_hash_fn_set_x (SCM table, SCM obj, SCM val,
                   scm_t_hash_fn hash_fn, scm_t_assoc_fn assoc_fn,
@@ -801,24 +306,7 @@ scm_hash_fn_set_x (SCM table, SCM obj, SCM val,
                                       hash_fn, assoc_fn, closure);
 
   if (!scm_is_eq (SCM_CDR (pair), val))
-    {
-      if (SCM_UNLIKELY (SCM_HASHTABLE_WEAK_VALUE_P (table)))
-        {
-          /* If the former value was on the heap, we need to unregister
-             the weak link.  */
-          SCM prev = weak_pair_cdr (pair);
-          
-          SCM_SETCDR (pair, val);
-
-          if (SCM_NIMP (prev) && !SCM_NIMP (val))
-            GC_unregister_disappearing_link ((GC_PTR) SCM_CDRLOC (pair));
-          else
-            SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) SCM_CDRLOC (pair),
-                                              (GC_PTR) SCM2PTR (val));
-        }
-      else
-        SCM_SETCDR (pair, val);
-    }
+    SCM_SETCDR (pair, val);
   
   return val;
 }
@@ -845,11 +333,7 @@ scm_hash_fn_remove_x (SCM table, SCM obj,
   if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
     scm_out_of_range (FUNC_NAME, scm_from_ulong (k));
 
-  if (SCM_HASHTABLE_WEAK_P (table))
-    h = weak_bucket_assoc (table, buckets, k, hash_fn,
-                          assoc_fn, obj, closure);
-  else
-    h = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
+  h = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
 
   if (scm_is_true (h))
     {
@@ -868,6 +352,9 @@ SCM_DEFINE (scm_hash_clear_x, "hash-clear!", 1, 0, 0,
            "Remove all items from @var{table} (without triggering a resize).")
 #define FUNC_NAME s_scm_hash_clear_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_clear_x (table);
+
   SCM_VALIDATE_HASHTABLE (SCM_ARG1, table);
 
   scm_vector_fill_x (SCM_HASHTABLE_VECTOR (table), SCM_EOL);
@@ -887,9 +374,6 @@ SCM_DEFINE (scm_hashq_get_handle, "hashq-get-handle", 2, 0, 
0,
            "Uses @code{eq?} for equality testing.")
 #define FUNC_NAME s_scm_hashq_get_handle
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_get_handle (table, key,
                                 (scm_t_hash_fn) scm_ihashq,
                                 (scm_t_assoc_fn) scm_sloppy_assq,
@@ -905,9 +389,6 @@ SCM_DEFINE (scm_hashq_create_handle_x, 
"hashq-create-handle!", 3, 0, 0,
            "associates @var{key} with @var{init}.")
 #define FUNC_NAME s_scm_hashq_create_handle_x
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_create_handle_x (table, key, init,
                                      (scm_t_hash_fn) scm_ihashq,
                                      (scm_t_assoc_fn) scm_sloppy_assq,
@@ -926,6 +407,10 @@ SCM_DEFINE (scm_hashq_ref, "hashq-ref", 2, 1, 0,
 {
   if (SCM_UNBNDP (dflt))
     dflt = SCM_BOOL_F;
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_refq (table, key, dflt);
+
   return scm_hash_fn_ref (table, key, dflt,
                          (scm_t_hash_fn) scm_ihashq,
                          (scm_t_assoc_fn) scm_sloppy_assq,
@@ -941,6 +426,9 @@ SCM_DEFINE (scm_hashq_set_x, "hashq-set!", 3, 0, 0,
            "store @var{value} there. Uses @code{eq?} for equality testing.")
 #define FUNC_NAME s_scm_hashq_set_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_putq_x (table, key, val);
+
   return scm_hash_fn_set_x (table, key, val,
                            (scm_t_hash_fn) scm_ihashq,
                            (scm_t_assoc_fn) scm_sloppy_assq,
@@ -956,6 +444,9 @@ SCM_DEFINE (scm_hashq_remove_x, "hashq-remove!", 2, 0, 0,
            "@var{table}.  Uses @code{eq?} for equality tests.")
 #define FUNC_NAME s_scm_hashq_remove_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_remq_x (table, key);
+
   return scm_hash_fn_remove_x (table, key,
                               (scm_t_hash_fn) scm_ihashq,
                               (scm_t_assoc_fn) scm_sloppy_assq,
@@ -974,9 +465,6 @@ SCM_DEFINE (scm_hashv_get_handle, "hashv-get-handle", 2, 0, 
0,
            "Uses @code{eqv?} for equality testing.")
 #define FUNC_NAME s_scm_hashv_get_handle
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_get_handle (table, key,
                                 (scm_t_hash_fn) scm_ihashv,
                                 (scm_t_assoc_fn) scm_sloppy_assv,
@@ -992,9 +480,6 @@ SCM_DEFINE (scm_hashv_create_handle_x, 
"hashv-create-handle!", 3, 0, 0,
            "associates @var{key} with @var{init}.")
 #define FUNC_NAME s_scm_hashv_create_handle_x
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_create_handle_x (table, key, init,
                                      (scm_t_hash_fn) scm_ihashv,
                                      (scm_t_assoc_fn) scm_sloppy_assv,
@@ -1003,6 +488,12 @@ SCM_DEFINE (scm_hashv_create_handle_x, 
"hashv-create-handle!", 3, 0, 0,
 #undef FUNC_NAME
 
 
+static int
+assv_predicate (SCM k, SCM v, void *closure)
+{
+  return scm_is_true (scm_eqv_p (k, PTR2SCM (closure)));
+}
+
 SCM_DEFINE (scm_hashv_ref, "hashv-ref", 2, 1, 0,
             (SCM table, SCM key, SCM dflt),
            "Look up @var{key} in the hash table @var{table}, and return the\n"
@@ -1013,6 +504,11 @@ SCM_DEFINE (scm_hashv_ref, "hashv-ref", 2, 1, 0,
 {
   if (SCM_UNBNDP (dflt))
     dflt = SCM_BOOL_F;
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_c_weak_table_ref (table, scm_ihashv (key, -1),
+                                 assv_predicate, SCM_PACK (key), dflt);
+
   return scm_hash_fn_ref (table, key, dflt,
                          (scm_t_hash_fn) scm_ihashv,
                          (scm_t_assoc_fn) scm_sloppy_assv,
@@ -1028,6 +524,14 @@ SCM_DEFINE (scm_hashv_set_x, "hashv-set!", 3, 0, 0,
            "store @var{value} there. Uses @code{eqv?} for equality testing.")
 #define FUNC_NAME s_scm_hashv_set_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      scm_c_weak_table_put_x (table, scm_ihashv (key, -1),
+                              assv_predicate, SCM_PACK (key),
+                              key, val);
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_set_x (table, key, val,
                            (scm_t_hash_fn) scm_ihashv,
                            (scm_t_assoc_fn) scm_sloppy_assv,
@@ -1042,6 +546,13 @@ SCM_DEFINE (scm_hashv_remove_x, "hashv-remove!", 2, 0, 0,
            "@var{table}.  Uses @code{eqv?} for equality tests.")
 #define FUNC_NAME s_scm_hashv_remove_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      scm_c_weak_table_remove_x (table, scm_ihashv (key, -1),
+                                 assv_predicate, SCM_PACK (key));
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_remove_x (table, key,
                               (scm_t_hash_fn) scm_ihashv,
                               (scm_t_assoc_fn) scm_sloppy_assv,
@@ -1059,9 +570,6 @@ SCM_DEFINE (scm_hash_get_handle, "hash-get-handle", 2, 0, 
0,
            "Uses @code{equal?} for equality testing.")
 #define FUNC_NAME s_scm_hash_get_handle
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_get_handle (table, key,
                                 (scm_t_hash_fn) scm_ihash,
                                 (scm_t_assoc_fn) scm_sloppy_assoc,
@@ -1077,9 +585,6 @@ SCM_DEFINE (scm_hash_create_handle_x, 
"hash-create-handle!", 3, 0, 0,
            "associates @var{key} with @var{init}.")
 #define FUNC_NAME s_scm_hash_create_handle_x
 {
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   return scm_hash_fn_create_handle_x (table, key, init,
                                      (scm_t_hash_fn) scm_ihash,
                                      (scm_t_assoc_fn) scm_sloppy_assoc,
@@ -1088,6 +593,12 @@ SCM_DEFINE (scm_hash_create_handle_x, 
"hash-create-handle!", 3, 0, 0,
 #undef FUNC_NAME
 
 
+static int
+assoc_predicate (SCM k, SCM v, void *closure)
+{
+  return scm_is_true (scm_equal_p (k, PTR2SCM (closure)));
+}
+
 SCM_DEFINE (scm_hash_ref, "hash-ref", 2, 1, 0,
             (SCM table, SCM key, SCM dflt),
            "Look up @var{key} in the hash table @var{table}, and return the\n"
@@ -1098,6 +609,11 @@ SCM_DEFINE (scm_hash_ref, "hash-ref", 2, 1, 0,
 {
   if (SCM_UNBNDP (dflt))
     dflt = SCM_BOOL_F;
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_c_weak_table_ref (table, scm_ihash (key, -1),
+                                 assoc_predicate, SCM_PACK (key), dflt);
+
   return scm_hash_fn_ref (table, key, dflt,
                          (scm_t_hash_fn) scm_ihash,
                          (scm_t_assoc_fn) scm_sloppy_assoc,
@@ -1114,6 +630,14 @@ SCM_DEFINE (scm_hash_set_x, "hash-set!", 3, 0, 0,
            "testing.")
 #define FUNC_NAME s_scm_hash_set_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      scm_c_weak_table_put_x (table, scm_ihash (key, -1),
+                              assoc_predicate, SCM_PACK (key),
+                              key, val);
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_set_x (table, key, val,
                            (scm_t_hash_fn) scm_ihash,
                            (scm_t_assoc_fn) scm_sloppy_assoc,
@@ -1129,6 +653,13 @@ SCM_DEFINE (scm_hash_remove_x, "hash-remove!", 2, 0, 0,
            "@var{table}.  Uses @code{equal?} for equality tests.")
 #define FUNC_NAME s_scm_hash_remove_x
 {
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      scm_c_weak_table_remove_x (table, scm_ihash (key, -1),
+                                 assoc_predicate, SCM_PACK (key));
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_remove_x (table, key,
                               (scm_t_hash_fn) scm_ihash,
                               (scm_t_assoc_fn) scm_sloppy_assoc,
@@ -1143,10 +674,9 @@ typedef struct scm_t_ihashx_closure
 {
   SCM hash;
   SCM assoc;
+  SCM key;
 } scm_t_ihashx_closure;
 
-
-
 static unsigned long
 scm_ihashx (SCM obj, unsigned long n, void *arg)
 {
@@ -1156,8 +686,6 @@ scm_ihashx (SCM obj, unsigned long n, void *arg)
   return scm_to_ulong (answer);
 }
 
-
-
 static SCM
 scm_sloppy_assx (SCM obj, SCM alist, void *arg)
 {
@@ -1165,6 +693,20 @@ scm_sloppy_assx (SCM obj, SCM alist, void *arg)
   return scm_call_2 (closure->assoc, obj, alist);
 }
 
+static int
+assx_predicate (SCM k, SCM v, void *closure)
+{
+  scm_t_ihashx_closure *c = (scm_t_ihashx_closure *) closure;
+
+  /* FIXME: The hashx interface is crazy.  Hash tables have nothing to
+     do with alists in principle.  Instead of getting an assoc proc,
+     hashx functions should use an equality predicate.  Perhaps we can
+     change this before 2.2, but until then, add a terrible, terrible
+     hack.  */
+
+  return scm_is_true (scm_call_2 (c->assoc, c->key, scm_acons (k, v, 
SCM_EOL)));
+}
+
 
 SCM_DEFINE (scm_hashx_get_handle, "hashx-get-handle", 4, 0, 0, 
             (SCM hash, SCM assoc, SCM table, SCM key),
@@ -1179,9 +721,7 @@ SCM_DEFINE (scm_hashx_get_handle, "hashx-get-handle", 4, 
0, 0,
   scm_t_ihashx_closure closure;
   closure.hash = hash;
   closure.assoc = assoc;
-
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
+  closure.key = key;
 
   return scm_hash_fn_get_handle (table, key, scm_ihashx, scm_sloppy_assx,
                                 (void *) &closure);
@@ -1202,9 +742,7 @@ SCM_DEFINE (scm_hashx_create_handle_x, 
"hashx-create-handle!", 5, 0, 0,
   scm_t_ihashx_closure closure;
   closure.hash = hash;
   closure.assoc = assoc;
-
-  if (SCM_UNLIKELY (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
+  closure.key = key;
 
   return scm_hash_fn_create_handle_x (table, key, init, scm_ihashx,
                                      scm_sloppy_assx, (void *)&closure);
@@ -1231,6 +769,15 @@ SCM_DEFINE (scm_hashx_ref, "hashx-ref", 4, 1, 0,
     dflt = SCM_BOOL_F;
   closure.hash = hash;
   closure.assoc = assoc;
+  closure.key = key;
+
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      unsigned long h = scm_to_ulong (scm_call_2 (hash, key,
+                                                  scm_from_ulong (-1)));
+      return scm_c_weak_table_ref (table, h, assx_predicate, &closure, dflt);
+    }
+
   return scm_hash_fn_ref (table, key, dflt, scm_ihashx, scm_sloppy_assx,
                          (void *)&closure);
 }
@@ -1255,6 +802,16 @@ SCM_DEFINE (scm_hashx_set_x, "hashx-set!", 5, 0, 0,
   scm_t_ihashx_closure closure;
   closure.hash = hash;
   closure.assoc = assoc;
+  closure.key = key;
+
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      unsigned long h = scm_to_ulong (scm_call_2 (hash, key,
+                                                  scm_from_ulong (-1)));
+      scm_c_weak_table_put_x (table, h, assx_predicate, &closure, key, val);
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_set_x (table, key, val, scm_ihashx, scm_sloppy_assx,
                            (void *)&closure);
 }
@@ -1276,6 +833,16 @@ SCM_DEFINE (scm_hashx_remove_x, "hashx-remove!", 4, 0, 0,
   scm_t_ihashx_closure closure;
   closure.hash = hash;
   closure.assoc = assoc;
+  closure.key = obj;
+
+  if (SCM_WEAK_TABLE_P (table))
+    {
+      unsigned long h = scm_to_ulong (scm_call_2 (hash, obj,
+                                                  scm_from_ulong (-1)));
+      scm_c_weak_table_remove_x (table, h, assx_predicate, &closure);
+      return SCM_UNSPECIFIED;
+    }
+
   return scm_hash_fn_remove_x (table, obj, scm_ihashx, scm_sloppy_assx,
                                (void *) &closure);
 }
@@ -1296,6 +863,10 @@ SCM_DEFINE (scm_hash_fold, "hash-fold", 3, 0, 0,
 #define FUNC_NAME s_scm_hash_fold
 {
   SCM_VALIDATE_PROC (1, proc);
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_fold (proc, init, table);
+
   SCM_VALIDATE_HASHTABLE (3, table);
   return scm_internal_hash_fold ((scm_t_hash_fold_fn) scm_call_3,
                                 (void *) SCM_UNPACK (proc), init, table);
@@ -1317,6 +888,10 @@ SCM_DEFINE (scm_hash_for_each, "hash-for-each", 2, 0, 0,
 #define FUNC_NAME s_scm_hash_for_each
 {
   SCM_VALIDATE_PROC (1, proc);
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_for_each (proc, table);
+
   SCM_VALIDATE_HASHTABLE (2, table);
   
   scm_internal_hash_for_each_handle (for_each_proc,
@@ -1335,9 +910,6 @@ SCM_DEFINE (scm_hash_for_each_handle, 
"hash-for-each-handle", 2, 0, 0,
   SCM_ASSERT (scm_is_true (scm_procedure_p (proc)), proc, 1, FUNC_NAME);
   SCM_VALIDATE_HASHTABLE (2, table);
   
-  if (SCM_UNLIKELY (SCM_HASHTABLE_WEAK_P (table)))
-    SCM_MISC_ERROR ("Handle access not permitted on weak table", SCM_EOL);
-
   scm_internal_hash_for_each_handle ((scm_t_hash_handle_fn) scm_call_1,
                                     (void *) SCM_UNPACK (proc),
                                     table);
@@ -1360,6 +932,10 @@ SCM_DEFINE (scm_hash_map_to_list, "hash-map->list", 2, 0, 
0,
 #define FUNC_NAME s_scm_hash_map_to_list
 {
   SCM_VALIDATE_PROC (1, proc);
+
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_weak_table_map_to_list (proc, table);
+
   SCM_VALIDATE_HASHTABLE (2, table);
   return scm_internal_hash_fold (map_proc,
                                 (void *) SCM_UNPACK (proc),
@@ -1378,6 +954,9 @@ scm_internal_hash_fold (scm_t_hash_fold_fn fn, void 
*closure,
   long i, n;
   SCM buckets, result = init;
   
+  if (SCM_WEAK_TABLE_P (table))
+    return scm_c_weak_table_fold (fn, closure, init, table);
+
   SCM_VALIDATE_HASHTABLE (0, table);
   buckets = SCM_HASHTABLE_VECTOR (table);
   
@@ -1390,14 +969,7 @@ scm_internal_hash_fold (scm_t_hash_fold_fn fn, void 
*closure,
           ls = SCM_CDR (ls))
        {
          handle = SCM_CAR (ls);
-
-         if (SCM_HASHTABLE_WEAK_P (table) && SCM_WEAK_PAIR_DELETED_P (handle))
-            /* Don't try to unlink this weak pair, as we're not within
-               the allocation lock.  Instead rely on
-               vacuum_weak_hash_table to do its job.  */
-            continue;
-          else
-            result = fn (closure, SCM_CAR (handle), SCM_CDR (handle), result);
+          result = fn (closure, SCM_CAR (handle), SCM_CDR (handle), result);
        }
     }
 
diff --git a/libguile/hashtab.h b/libguile/hashtab.h
index 3149946..fdd746c 100644
--- a/libguile/hashtab.h
+++ b/libguile/hashtab.h
@@ -3,7 +3,7 @@
 #ifndef SCM_HASHTAB_H
 #define SCM_HASHTAB_H
 
-/* Copyright (C) 1995,1996,1999,2000,2001, 2003, 2004, 2006, 2008, 2009 Free 
Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1999,2000,2001, 2003, 2004, 2006, 2008, 2009, 2011 
Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -25,29 +25,14 @@
 
 #include "libguile/__scm.h"
 
-#include "weaks.h"
-
 
 
-#define SCM_HASHTABLEF_WEAK_CAR SCM_WVECTF_WEAK_KEY
-#define SCM_HASHTABLEF_WEAK_CDR SCM_WVECTF_WEAK_VALUE
-
 #define SCM_HASHTABLE_P(x) (!SCM_IMP (x) && SCM_TYP7(x) == scm_tc7_hashtable)
 #define SCM_VALIDATE_HASHTABLE(pos, arg) \
   SCM_MAKE_VALIDATE_MSG (pos, arg, HASHTABLE_P, "hash-table")
 #define SCM_HASHTABLE_VECTOR(h)  SCM_CELL_OBJECT_1 (h)
 #define SCM_SET_HASHTABLE_VECTOR(x, v) SCM_SET_CELL_OBJECT_1 ((x), (v))
 #define SCM_HASHTABLE(x)          ((scm_t_hashtable *) SCM_CELL_WORD_2 (x))
-#define SCM_HASHTABLE_FLAGS(x)    (SCM_HASHTABLE (x)->flags)
-#define SCM_HASHTABLE_WEAK_KEY_P(x) \
-  (SCM_HASHTABLE_FLAGS (x) & SCM_HASHTABLEF_WEAK_CAR)
-#define SCM_HASHTABLE_WEAK_VALUE_P(x) \
-  (SCM_HASHTABLE_FLAGS (x) & SCM_HASHTABLEF_WEAK_CDR)
-#define SCM_HASHTABLE_DOUBLY_WEAK_P(x)                         \
-  ((SCM_HASHTABLE_FLAGS (x)                                    \
-    & (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR))     \
-   == (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR))
-#define SCM_HASHTABLE_WEAK_P(x)           SCM_HASHTABLE_FLAGS (x)
 #define SCM_HASHTABLE_N_ITEMS(x)   (SCM_HASHTABLE (x)->n_items)
 #define SCM_SET_HASHTABLE_N_ITEMS(x, n)   (SCM_HASHTABLE (x)->n_items = n)
 #define SCM_HASHTABLE_INCREMENT(x) (SCM_HASHTABLE_N_ITEMS(x)++)
@@ -70,10 +55,6 @@ typedef unsigned long (*scm_t_hash_fn) (SCM obj, unsigned 
long max,
    some equality predicate.  */
 typedef SCM (*scm_t_assoc_fn) (SCM obj, SCM alist, void *closure);
 
-/* Function that returns true if the given object is the one we are
-   looking for, for scm_hash_fn_ref_by_hash.  */
-typedef int (*scm_t_hash_predicate_fn) (SCM obj, void *closure);
-
 /* Function to fold over the entries of a hash table.  */
 typedef SCM (*scm_t_hash_fold_fn) (void *closure, SCM key, SCM value,
                                   SCM result);
@@ -83,7 +64,6 @@ typedef SCM (*scm_t_hash_fold_fn) (void *closure, SCM key, 
SCM value,
 typedef SCM (*scm_t_hash_handle_fn) (void *closure, SCM handle);
 
 typedef struct scm_t_hashtable {
-  int flags;                   /* properties of table */
   unsigned long n_items;       /* number of items in table */
   unsigned long lower;         /* when to shrink */
   unsigned long upper;         /* when to grow */
@@ -97,14 +77,8 @@ typedef struct scm_t_hashtable {
 SCM_API SCM scm_vector_to_hash_table (SCM vector);
 SCM_API SCM scm_c_make_hash_table (unsigned long k);
 SCM_API SCM scm_make_hash_table (SCM n);
-SCM_API SCM scm_make_weak_key_hash_table (SCM k);
-SCM_API SCM scm_make_weak_value_hash_table (SCM k);
-SCM_API SCM scm_make_doubly_weak_hash_table (SCM k);
 
 SCM_API SCM scm_hash_table_p (SCM h);
-SCM_API SCM scm_weak_key_hash_table_p (SCM h);
-SCM_API SCM scm_weak_value_hash_table_p (SCM h);
-SCM_API SCM scm_doubly_weak_hash_table_p (SCM h);
 
 SCM_INTERNAL void scm_i_rehash (SCM table, scm_t_hash_fn hash_fn,
                                void *closure, const char *func_name);
@@ -114,10 +88,6 @@ SCM_API SCM scm_hash_fn_get_handle (SCM table, SCM obj,
                                    scm_t_hash_fn hash_fn,
                                    scm_t_assoc_fn assoc_fn,
                                    void *closure);
-SCM_INTERNAL
-SCM scm_hash_fn_get_handle_by_hash (SCM table, unsigned long raw_hash,
-                                    scm_t_hash_predicate_fn predicate_fn,
-                                    void *closure);
 SCM_API SCM scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init,
                                         scm_t_hash_fn hash_fn,
                                         scm_t_assoc_fn assoc_fn,
diff --git a/libguile/init.c b/libguile/init.c
index d288a73..130725c 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -133,7 +133,6 @@
 #include "libguile/version.h"
 #include "libguile/vm.h"
 #include "libguile/vports.h"
-#include "libguile/weaks.h"
 #include "libguile/guardians.h"
 #include "libguile/extensions.h"
 #include "libguile/uniform.h"
@@ -383,11 +382,11 @@ scm_i_init_guile (void *base)
 
   scm_storage_prehistory ();
   scm_threads_prehistory (base);  /* requires storage_prehistory */
-  scm_weaks_prehistory ();        /* requires storage_prehistory */
+  scm_weak_table_prehistory ();        /* requires storage_prehistory */
 #ifdef GUILE_DEBUG_MALLOC
   scm_debug_malloc_prehistory ();
 #endif
-  scm_symbols_prehistory ();      /* requires weaks_prehistory */
+  scm_symbols_prehistory ();      /* requires weak_table_prehistory */
   scm_modules_prehistory ();
   scm_init_array_handle ();
   scm_bootstrap_bytevectors ();   /* Requires array-handle */
@@ -488,8 +487,9 @@ scm_i_init_guile (void *base)
   scm_init_throw ();    /* Requires smob_prehistory */
   scm_init_trees ();
   scm_init_version ();
-  scm_init_weaks ();
   scm_init_weak_set ();
+  scm_init_weak_table ();
+  scm_init_weak_vectors ();
   scm_init_guardians (); /* requires smob_prehistory */
   scm_init_vports ();
   scm_init_standard_ports ();  /* Requires fports */
diff --git a/libguile/modules.c b/libguile/modules.c
index 6c3f262..971676c 100644
--- a/libguile/modules.c
+++ b/libguile/modules.c
@@ -960,16 +960,8 @@ SCM_DEFINE (scm_module_reverse_lookup, 
"module-reverse-lookup", 2, 0, 0,
        {
          handle = SCM_CAR (ls);
 
-         if (SCM_UNPACK (SCM_CAR (handle)) == 0)
-           {
-             /* FIXME: We hit a weak pair whose car has become unreachable.
-                We should remove the pair in question or something.  */
-           }
-         else
-           {
-             if (scm_is_eq (SCM_CDR (handle), variable))
-               return SCM_CAR (handle);
-           }
+          if (scm_is_eq (SCM_CDR (handle), variable))
+            return SCM_CAR (handle);
 
          ls = SCM_CDR (ls);
        }
diff --git a/libguile/objprop.c b/libguile/objprop.c
index 7b50d71..3a57d28 100644
--- a/libguile/objprop.c
+++ b/libguile/objprop.c
@@ -27,7 +27,6 @@
 #include "libguile/hashtab.h"
 #include "libguile/alist.h"
 #include "libguile/root.h"
-#include "libguile/weaks.h"
 
 #include "libguile/objprop.h"
 
@@ -36,20 +35,13 @@
  */
 
 static SCM object_whash;
-static scm_i_pthread_mutex_t whash_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 SCM_DEFINE (scm_object_properties, "object-properties", 1, 0, 0, 
            (SCM obj),
            "Return @var{obj}'s property list.")
 #define FUNC_NAME s_scm_object_properties
 {
-  SCM ret;
-
-  scm_i_pthread_mutex_lock (&whash_mutex);
-  ret = scm_hashq_ref (object_whash, obj, SCM_EOL);
-  scm_i_pthread_mutex_unlock (&whash_mutex);
-
-  return ret;
+  return scm_weak_table_refq (object_whash, obj, SCM_EOL);
 }
 #undef FUNC_NAME
 
@@ -59,9 +51,7 @@ SCM_DEFINE (scm_set_object_properties_x, 
"set-object-properties!", 2, 0, 0,
            "Set @var{obj}'s property list to @var{alist}.")
 #define FUNC_NAME s_scm_set_object_properties_x
 {
-  scm_i_pthread_mutex_lock (&whash_mutex);
-  scm_hashq_set_x (object_whash, obj, alist);
-  scm_i_pthread_mutex_unlock (&whash_mutex);
+  scm_weak_table_putq_x (object_whash, obj, alist);
 
   return alist;
 }
@@ -87,14 +77,14 @@ SCM_DEFINE (scm_set_object_property_x, 
"set-object-property!", 3, 0, 0,
   SCM alist;
   SCM assoc;
 
-  scm_i_pthread_mutex_lock (&whash_mutex);
-  alist = scm_hashq_ref (object_whash, obj, SCM_EOL);
+  scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
+  alist = scm_weak_table_refq (object_whash, obj, SCM_EOL);
   assoc = scm_assq (key, alist);
   if (SCM_NIMP (assoc))
     SCM_SETCDR (assoc, value);
   else
-    scm_hashq_set_x (object_whash, obj, scm_acons (key, value, alist));
-  scm_i_pthread_mutex_unlock (&whash_mutex);
+    scm_weak_table_putq_x (object_whash, obj, scm_acons (key, value, alist));
+  scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
 
   return value;
 }
@@ -104,7 +94,7 @@ SCM_DEFINE (scm_set_object_property_x, 
"set-object-property!", 3, 0, 0,
 void
 scm_init_objprop ()
 {
-  object_whash = scm_make_weak_key_hash_table (SCM_UNDEFINED);
+  object_whash = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
 #include "libguile/objprop.x"
 }
 
diff --git a/libguile/print.c b/libguile/print.c
index a619bfe..e462d12 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -40,7 +40,6 @@
 #include "libguile/macros.h"
 #include "libguile/procprop.h"
 #include "libguile/read.h"
-#include "libguile/weaks.h"
 #include "libguile/programs.h"
 #include "libguile/alist.h"
 #include "libguile/struct.h"
@@ -624,6 +623,9 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
        case scm_tc7_weak_set:
          scm_i_weak_set_print (exp, port, pstate);
          break;
+       case scm_tc7_weak_table:
+         scm_i_weak_table_print (exp, port, pstate);
+         break;
        case scm_tc7_fluid:
          scm_i_fluid_print (exp, port, pstate);
          break;
@@ -650,10 +652,7 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
          break;
        case scm_tc7_wvect:
          ENTER_NESTED_DATA (pstate, exp, circref);
-         if (SCM_IS_WHVEC (exp))
-           scm_puts ("#wh(", port);
-         else
-           scm_puts ("#w(", port);
+          scm_puts ("#w(", port);
          goto common_vector_printer;
 
        case scm_tc7_bytevector:
@@ -673,26 +672,11 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
                last = pstate->length - 1;
                cutp = 1;
              }
-           if (SCM_I_WVECTP (exp))
-             {
-               /* Elements of weak vectors may not be accessed via the
-                  `SIMPLE_VECTOR_REF ()' macro.  */
-               for (i = 0; i < last; ++i)
-                 {
-                   scm_iprin1 (scm_c_vector_ref (exp, i),
-                               port, pstate);
-                   scm_putc (' ', port);
-                 }
-             }
-           else
-             {
-               for (i = 0; i < last; ++i)
-                 {
-                   scm_iprin1 (SCM_SIMPLE_VECTOR_REF (exp, i), port, pstate);
-                   scm_putc (' ', port);
-                 }
-             }
-
+            for (i = 0; i < last; ++i)
+              {
+                scm_iprin1 (scm_c_vector_ref (exp, i), port, pstate);
+                scm_putc (' ', port);
+              }
            if (i == last)
              {
                /* CHECK_INTS; */
diff --git a/libguile/procprop.c b/libguile/procprop.c
index ac2fa12..8d5b162 100644
--- a/libguile/procprop.c
+++ b/libguile/procprop.c
@@ -31,7 +31,7 @@
 #include "libguile/smob.h"
 #include "libguile/root.h"
 #include "libguile/vectors.h"
-#include "libguile/hashtab.h"
+#include "libguile/weak-table.h"
 #include "libguile/programs.h"
 
 #include "libguile/validate.h"
@@ -42,7 +42,6 @@ SCM_GLOBAL_SYMBOL (scm_sym_system_procedure, 
"system-procedure");
 SCM_GLOBAL_SYMBOL (scm_sym_name, "name");
 
 static SCM overrides;
-static scm_i_pthread_mutex_t overrides_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 int
 scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest)
@@ -104,9 +103,7 @@ SCM_DEFINE (scm_procedure_properties, 
"procedure-properties", 1, 0, 0,
   
   SCM_VALIDATE_PROC (1, proc);
 
-  scm_i_pthread_mutex_lock (&overrides_lock);
-  ret = scm_hashq_ref (overrides, proc, SCM_BOOL_F);
-  scm_i_pthread_mutex_unlock (&overrides_lock);
+  ret = scm_weak_table_refq (overrides, proc, SCM_BOOL_F);
 
   if (scm_is_false (ret))
     {
@@ -127,9 +124,7 @@ SCM_DEFINE (scm_set_procedure_properties_x, 
"set-procedure-properties!", 2, 0, 0
 {
   SCM_VALIDATE_PROC (1, proc);
 
-  scm_i_pthread_mutex_lock (&overrides_lock);
-  scm_hashq_set_x (overrides, proc, alist);
-  scm_i_pthread_mutex_unlock (&overrides_lock);
+  scm_weak_table_putq_x (overrides, proc, alist);
 
   return SCM_UNSPECIFIED;
 }
@@ -156,8 +151,8 @@ SCM_DEFINE (scm_set_procedure_property_x, 
"set-procedure-property!", 3, 0, 0,
 
   SCM_VALIDATE_PROC (1, proc);
 
-  scm_i_pthread_mutex_lock (&overrides_lock);
-  props = scm_hashq_ref (overrides, proc, SCM_BOOL_F);
+  scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
+  props = scm_weak_table_refq (overrides, proc, SCM_BOOL_F);
   if (scm_is_false (props))
     {
       if (SCM_PROGRAM_P (proc))
@@ -165,8 +160,8 @@ SCM_DEFINE (scm_set_procedure_property_x, 
"set-procedure-property!", 3, 0, 0,
       else
         props = SCM_EOL;
     }
-  scm_hashq_set_x (overrides, proc, scm_assq_set_x (props, key, val));
-  scm_i_pthread_mutex_unlock (&overrides_lock);
+  scm_weak_table_putq_x (overrides, proc, scm_assq_set_x (props, key, val));
+  scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
 
   return SCM_UNSPECIFIED;
 }
@@ -178,7 +173,7 @@ SCM_DEFINE (scm_set_procedure_property_x, 
"set-procedure-property!", 3, 0, 0,
 void
 scm_init_procprop ()
 {
-  overrides = scm_make_weak_key_hash_table (SCM_UNDEFINED);
+  overrides = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
 #include "libguile/procprop.x"
 }
 
diff --git a/libguile/smob.c b/libguile/smob.c
index ef3f564..ab8208c 100644
--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -418,16 +418,13 @@ scm_set_smob_apply (scm_t_bits tc, SCM (*apply) (),
 }
 
 static SCM tramp_weak_map = SCM_BOOL_F;
-static scm_i_pthread_mutex_t tramp_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 SCM
 scm_i_smob_apply_trampoline (SCM smob)
 {
   SCM tramp;
 
-  scm_i_pthread_mutex_lock (&tramp_lock);
-  tramp = scm_hashq_ref (tramp_weak_map, smob, SCM_BOOL_F);
-  scm_i_pthread_mutex_unlock (&tramp_lock);
+  tramp = scm_weak_table_refq (tramp_weak_map, smob, SCM_BOOL_F);
 
   if (scm_is_true (tramp))
     return tramp;
@@ -447,9 +444,7 @@ scm_i_smob_apply_trampoline (SCM smob)
 
       /* Race conditions (between the ref and this set!) cannot cause
          any harm here.  */
-      scm_i_pthread_mutex_lock (&tramp_lock);
-      scm_hashq_set_x (tramp_weak_map, smob, tramp);
-      scm_i_pthread_mutex_unlock (&tramp_lock);
+      scm_weak_table_putq_x (tramp_weak_map, smob, tramp);
       return tramp;
     }
 }
@@ -677,7 +672,7 @@ scm_smob_prehistory ()
       scm_smobs[i].apply_trampoline_objcode = SCM_BOOL_F;
     }
 
-  tramp_weak_map = scm_make_weak_key_hash_table (SCM_UNDEFINED);
+  tramp_weak_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
 }
 
 /*
diff --git a/libguile/snarf.h b/libguile/snarf.h
index 1c072ba..4aaff7c 100644
--- a/libguile/snarf.h
+++ b/libguile/snarf.h
@@ -119,9 +119,9 @@ SCM_SNARF_HERE(                                             
                \
 )                                                                      \
 SCM_SNARF_INIT(                                                        \
   /* Initialize the foreign.  */                                        \
-  scm_i_paste (FNAME, __raw_objtable)[2] = scm_i_paste (FNAME, 
__subr_foreign); \
+  scm_i_paste (FNAME, __raw_objtable)[1] = scm_i_paste (FNAME, 
__subr_foreign); \
   /* Initialize the procedure name (an interned symbol).  */           \
-  scm_i_paste (FNAME, __raw_objtable)[3] = scm_i_paste (FNAME, __name); \
+  scm_i_paste (FNAME, __raw_objtable)[2] = scm_i_paste (FNAME, __name); \
   /* Initialize the objcode trampoline.  */                             \
   SCM_SET_CELL_OBJECT (scm_i_paste (FNAME, __subr), 1,                  \
                        scm_subr_objcode_trampoline (REQ, OPT, VAR));    \
@@ -366,12 +366,11 @@ SCM_SNARF_INIT(scm_set_smob_apply((tag), (c_name), (req), 
(opt), (rest));)
 
 /* for primitive-generics, add a foreign to the end */
 #define SCM_STATIC_SUBR_OBJVECT(c_name, foreign)                        \
-  static SCM_ALIGNED (8) SCM c_name[4] =                                \
+  static SCM_ALIGNED (8) SCM c_name[3] =                                \
   {                                                                     \
     SCM_PACK (scm_tc7_vector | (2 << 8)),                               \
-    SCM_PACK (0),                                                       \
     foreign,                                                            \
-    SCM_BOOL_F, /* the name */                                          \
+    SCM_BOOL_F /* the name */                                           \
   }
 
 #define SCM_STATIC_PROGRAM(c_name, objcode, objtable, freevars)         \
diff --git a/libguile/srcprop.c b/libguile/srcprop.c
index dc333d4..cd16789 100644
--- a/libguile/srcprop.c
+++ b/libguile/srcprop.c
@@ -33,7 +33,6 @@
 #include "libguile/hash.h"
 #include "libguile/ports.h"
 #include "libguile/root.h"
-#include "libguile/weaks.h"
 #include "libguile/gc.h"
 
 #include "libguile/validate.h"
@@ -61,7 +60,6 @@ SCM_GLOBAL_SYMBOL (scm_sym_line, "line");
 SCM_GLOBAL_SYMBOL (scm_sym_column, "column");
 
 static SCM scm_source_whash;
-static scm_i_pthread_mutex_t source_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 
 /*
@@ -167,9 +165,7 @@ SCM_DEFINE (scm_source_properties, "source-properties", 1, 
0, 0,
   SCM p;
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  p = scm_hashq_ref (scm_source_whash, obj, SCM_EOL); 
-  scm_i_pthread_mutex_unlock (&source_lock);
+  p = scm_weak_table_refq (scm_source_whash, obj, SCM_EOL); 
 
   if (SRCPROPSP (p))
     return scm_srcprops_to_alist (p);
@@ -189,9 +185,7 @@ SCM_DEFINE (scm_set_source_properties_x, 
"set-source-properties!", 2, 0, 0,
 {
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  scm_hashq_set_x (scm_source_whash, obj, alist);
-  scm_i_pthread_mutex_unlock (&source_lock);
+  scm_weak_table_putq_x (scm_source_whash, obj, alist);
 
   return alist;
 }
@@ -205,9 +199,7 @@ scm_i_has_source_properties (SCM obj)
   
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  ret = scm_is_true (scm_hashq_ref (scm_source_whash, obj, SCM_BOOL_F));
-  scm_i_pthread_mutex_unlock (&source_lock);
+  ret = scm_is_true (scm_weak_table_refq (scm_source_whash, obj, SCM_BOOL_F));
 
   return ret;
 }
@@ -220,14 +212,12 @@ scm_i_set_source_properties_x (SCM obj, long line, int 
col, SCM fname)
 {
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  scm_hashq_set_x (scm_source_whash, obj,
-                   scm_make_srcprops (line, col, fname,
-                                      SCM_COPY_SOURCE_P
-                                      ? scm_copy_tree (obj)
-                                      : SCM_UNDEFINED,
-                                      SCM_EOL));
-  scm_i_pthread_mutex_unlock (&source_lock);
+  scm_weak_table_putq_x (scm_source_whash, obj,
+                         scm_make_srcprops (line, col, fname,
+                                            SCM_COPY_SOURCE_P
+                                            ? scm_copy_tree (obj)
+                                            : SCM_UNDEFINED,
+                                            SCM_EOL));
 }
 #undef FUNC_NAME
 
@@ -240,9 +230,7 @@ SCM_DEFINE (scm_source_property, "source-property", 2, 0, 0,
   SCM p;
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  p = scm_hashq_ref (scm_source_whash, obj, SCM_EOL);
-  scm_i_pthread_mutex_unlock (&source_lock);
+  p = scm_weak_table_refq (scm_source_whash, obj, SCM_EOL);
 
   if (!SRCPROPSP (p))
     goto alist;
@@ -272,44 +260,44 @@ SCM_DEFINE (scm_set_source_property_x, 
"set-source-property!", 3, 0, 0,
   SCM p;
   SCM_VALIDATE_NIM (1, obj);
 
-  scm_i_pthread_mutex_lock (&source_lock);
-  p = scm_hashq_ref (scm_source_whash, obj, SCM_EOL);
+  scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
+  p = scm_weak_table_refq (scm_source_whash, obj, SCM_EOL);
 
   if (scm_is_eq (scm_sym_line, key))
     {
       if (SRCPROPSP (p))
        SETSRCPROPLINE (p, scm_to_int (datum));
       else
-       scm_hashq_set_x (scm_source_whash, obj,
-                         scm_make_srcprops (scm_to_int (datum), 0,
-                                            SCM_UNDEFINED, SCM_UNDEFINED, p));
+       scm_weak_table_putq_x (scm_source_whash, obj,
+                               scm_make_srcprops (scm_to_int (datum), 0,
+                                                  SCM_UNDEFINED, 
SCM_UNDEFINED, p));
     }
   else if (scm_is_eq (scm_sym_column, key))
     {
       if (SRCPROPSP (p))
        SETSRCPROPCOL (p, scm_to_int (datum));
       else
-       scm_hashq_set_x (scm_source_whash, obj,
-                         scm_make_srcprops (0, scm_to_int (datum),
-                                            SCM_UNDEFINED, SCM_UNDEFINED, p));
+       scm_weak_table_putq_x (scm_source_whash, obj,
+                               scm_make_srcprops (0, scm_to_int (datum),
+                                                  SCM_UNDEFINED, 
SCM_UNDEFINED, p));
     }
   else if (scm_is_eq (scm_sym_copy, key))
     {
       if (SRCPROPSP (p))
        SETSRCPROPCOPY (p, datum);
       else
-       scm_hashq_set_x (scm_source_whash, obj,
-                         scm_make_srcprops (0, 0, SCM_UNDEFINED, datum, p));
+       scm_weak_table_putq_x (scm_source_whash, obj,
+                               scm_make_srcprops (0, 0, SCM_UNDEFINED, datum, 
p));
     }
   else
     {
       if (SRCPROPSP (p))
        SETSRCPROPALIST (p, scm_acons (key, datum, SRCPROPALIST (p)));
       else
-       scm_hashq_set_x (scm_source_whash, obj,
-                         scm_acons (key, datum, p));
+       scm_weak_table_putq_x (scm_source_whash, obj,
+                               scm_acons (key, datum, p));
     }
-  scm_i_pthread_mutex_unlock (&source_lock);
+  scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
 
   return SCM_UNSPECIFIED;
 }
@@ -325,12 +313,10 @@ SCM_DEFINE (scm_cons_source, "cons-source", 3, 0, 0,
 {
   SCM p, z;
   z = scm_cons (x, y);
-  scm_i_pthread_mutex_lock (&source_lock);
   /* Copy source properties possibly associated with xorig. */
-  p = scm_hashq_ref (scm_source_whash, xorig, SCM_BOOL_F);
+  p = scm_weak_table_refq (scm_source_whash, xorig, SCM_BOOL_F);
   if (scm_is_true (p))
-    scm_hashq_set_x (scm_source_whash, z, p);
-  scm_i_pthread_mutex_unlock (&source_lock);
+    scm_weak_table_putq_x (scm_source_whash, z, p);
   return z;
 }
 #undef FUNC_NAME
@@ -342,7 +328,7 @@ scm_init_srcprop ()
   scm_tc16_srcprops = scm_make_smob_type ("srcprops", 0);
   scm_set_smob_print (scm_tc16_srcprops, srcprops_print);
 
-  scm_source_whash = scm_make_weak_key_hash_table (scm_from_int (2047));
+  scm_source_whash = scm_c_make_weak_table (2047, SCM_WEAK_TABLE_KIND_KEY);
   scm_c_define ("source-whash", scm_source_whash);
 
   scm_last_alist_filename = scm_cons (SCM_EOL,
diff --git a/libguile/struct.c b/libguile/struct.c
index 4a2a9d7..7f8f75d 100644
--- a/libguile/struct.c
+++ b/libguile/struct.c
@@ -29,7 +29,6 @@
 #include "libguile/chars.h"
 #include "libguile/eval.h"
 #include "libguile/alist.h"
-#include "libguile/weaks.h"
 #include "libguile/hashtab.h"
 #include "libguile/ports.h"
 #include "libguile/strings.h"
diff --git a/libguile/tags.h b/libguile/tags.h
index f5a07dc..c0ab34c 100644
--- a/libguile/tags.h
+++ b/libguile/tags.h
@@ -418,7 +418,7 @@ typedef union SCM { struct { scm_t_bits n; } n; } SCM;
 #define scm_tc7_unused_19      69
 #define scm_tc7_program                79
 #define scm_tc7_weak_set       85
-#define scm_tc7_unused_10      87
+#define scm_tc7_weak_table     87
 #define scm_tc7_unused_20      93
 #define scm_tc7_unused_11      95
 #define scm_tc7_unused_12      101
diff --git a/libguile/threads.c b/libguile/threads.c
index fcd1c1d..2560b69 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -56,7 +56,6 @@
 #include "libguile/init.h"
 #include "libguile/scmsigs.h"
 #include "libguile/strings.h"
-#include "libguile/weaks.h"
 
 #include <full-read.h>
 
@@ -651,9 +650,9 @@ do_thread_exit (void *v)
 
   while (!scm_is_null (t->mutexes))
     {
-      SCM mutex = SCM_WEAK_PAIR_CAR (t->mutexes);
+      SCM mutex = scm_c_weak_vector_ref (scm_car (t->mutexes), 0);
 
-      if (!SCM_UNBNDP (mutex))
+      if (scm_is_true (mutex))
        {
          fat_mutex *m  = SCM_MUTEX_DATA (mutex);
 
@@ -667,7 +666,7 @@ do_thread_exit (void *v)
          scm_i_pthread_mutex_unlock (&m->lock);
        }
 
-      t->mutexes = SCM_WEAK_PAIR_CDR (t->mutexes);
+      t->mutexes = scm_cdr (t->mutexes);
     }
 
   scm_i_pthread_mutex_unlock (&t->admin_mutex);
@@ -1376,7 +1375,8 @@ fat_mutex_lock (SCM mutex, scm_t_timespec *timeout, SCM 
owner, int *ret)
                 The weak pair itself is eventually removed when MUTEX
                 is unlocked.  Note that `t->mutexes' lists mutexes
                 currently held by T, so it should be small.  */
-             t->mutexes = scm_weak_car_pair (mutex, t->mutexes);
+              t->mutexes = scm_cons (scm_make_weak_vector (SCM_INUM1, mutex),
+                                     t->mutexes);
 
              scm_i_pthread_mutex_unlock (&t->admin_mutex);
            }
@@ -1520,6 +1520,25 @@ typedef struct {
 #define SCM_CONDVARP(x)       SCM_SMOB_PREDICATE (scm_tc16_condvar, x)
 #define SCM_CONDVAR_DATA(x)   ((fat_cond *) SCM_SMOB_DATA (x))
 
+static void
+remove_mutex_from_thread (SCM mutex, scm_i_thread *t)
+{
+  SCM walk, prev;
+  
+  for (prev = SCM_BOOL_F, walk = t->mutexes; scm_is_pair (walk);
+       walk = SCM_CDR (walk))
+    {
+      if (scm_is_eq (mutex, scm_c_weak_vector_ref (SCM_CAR (walk), 0)))
+        {
+          if (scm_is_pair (prev))
+            SCM_SETCDR (prev, SCM_CDR (walk));
+          else
+            t->mutexes = SCM_CDR (walk);
+          break;
+        }
+    }
+}
+
 static int
 fat_mutex_unlock (SCM mutex, SCM cond,
                  const scm_t_timespec *waittime, int relock)
@@ -1564,7 +1583,7 @@ fat_mutex_unlock (SCM mutex, SCM cond,
          if (m->level == 0)
            {
              /* Change the owner of MUTEX.  */
-             t->mutexes = scm_delq_x (mutex, t->mutexes);
+             remove_mutex_from_thread (mutex, t);
              m->owner = unblock_from_queue (m->waiting);
            }
 
@@ -1612,7 +1631,7 @@ fat_mutex_unlock (SCM mutex, SCM cond,
       if (m->level == 0)
        {
          /* Change the owner of MUTEX.  */
-         t->mutexes = scm_delq_x (mutex, t->mutexes);
+         remove_mutex_from_thread (mutex, t);
          m->owner = unblock_from_queue (m->waiting);
        }
 
diff --git a/libguile/vectors.c b/libguile/vectors.c
index e43fa0e..1640725 100644
--- a/libguile/vectors.c
+++ b/libguile/vectors.c
@@ -67,9 +67,7 @@ scm_vector_elements (SCM vec, scm_t_array_handle *h,
                     size_t *lenp, ssize_t *incp)
 {
   if (SCM_I_WVECTP (vec))
-    /* FIXME: We should check each (weak) element of the vector for NULL and
-       convert it to SCM_BOOL_F.  */
-    abort ();
+    scm_wrong_type_arg_msg (NULL, 0, vec, "non-weak vector");
 
   scm_generalized_vector_get_handle (vec, h);
   if (lenp)
@@ -86,9 +84,7 @@ scm_vector_writable_elements (SCM vec, scm_t_array_handle *h,
                              size_t *lenp, ssize_t *incp)
 {
   if (SCM_I_WVECTP (vec))
-    /* FIXME: We should check each (weak) element of the vector for NULL and
-       convert it to SCM_BOOL_F.  */
-    abort ();
+    scm_wrong_type_arg_msg (NULL, 0, vec, "non-weak vector");
 
   scm_generalized_vector_get_handle (vec, h);
   if (lenp)
@@ -205,40 +201,29 @@ scm_vector_ref (SCM v, SCM k)
 SCM
 scm_c_vector_ref (SCM v, size_t k)
 {
-  if (SCM_I_IS_VECTOR (v))
+  if (SCM_I_IS_NONWEAK_VECTOR (v))
     {
-      register SCM elt;
-
       if (k >= SCM_I_VECTOR_LENGTH (v))
        scm_out_of_range (NULL, scm_from_size_t (k));
-      elt = (SCM_I_VECTOR_ELTS(v))[k];
-
-      if (SCM_UNPACK (elt) == 0 && SCM_I_WVECTP (v))
-       /* ELT was a weak pointer and got nullified by the GC.  */
-       return SCM_BOOL_F;
-
-      return elt;
+      return SCM_SIMPLE_VECTOR_REF (v, k);
     }
+  else if (SCM_I_WVECTP (v))
+    return scm_c_weak_vector_ref (v, k);
   else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
     {
       scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
       SCM vv = SCM_I_ARRAY_V (v);
-      if (SCM_I_IS_VECTOR (vv))
-       {
-         register SCM elt;
-
-         if (k >= dim->ubnd - dim->lbnd + 1)
-           scm_out_of_range (NULL, scm_from_size_t (k));
-         k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
-         elt = (SCM_I_VECTOR_ELTS (vv))[k];
-
-         if (SCM_UNPACK (elt) == 0 && (SCM_I_WVECTP (vv)))
-           /* ELT was a weak pointer and got nullified by the GC.  */
-           return SCM_BOOL_F;
-
-         return elt;
-       }
-      scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
+
+      k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
+      if (k >= dim->ubnd - dim->lbnd + 1)
+        scm_out_of_range (NULL, scm_from_size_t (k));
+
+      if (SCM_I_IS_NONWEAK_VECTOR (vv))
+        return SCM_SIMPLE_VECTOR_REF (vv, k);
+      else if (SCM_I_WVECTP (vv))
+        return scm_c_weak_vector_ref (vv, k);
+      else
+        scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
     }
   else
     return scm_wta_dispatch_2 (g_vector_ref, v, scm_from_size_t (k), 2,
@@ -270,38 +255,27 @@ scm_vector_set_x (SCM v, SCM k, SCM obj)
 void
 scm_c_vector_set_x (SCM v, size_t k, SCM obj)
 {
-  if (SCM_I_IS_VECTOR (v))
+  if (SCM_I_IS_NONWEAK_VECTOR (v))
     {
       if (k >= SCM_I_VECTOR_LENGTH (v))
-       scm_out_of_range (NULL, scm_from_size_t (k)); 
-      (SCM_I_VECTOR_WELTS(v))[k] = obj;
-      if (SCM_I_WVECTP (v))
-       {
-         /* Make it a weak pointer.  */
-         GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (v))[k]);
-         SCM_I_REGISTER_DISAPPEARING_LINK (link,
-                                            (GC_PTR) SCM2PTR (obj));
-       }
+        scm_out_of_range (NULL, scm_from_size_t (k)); 
+      SCM_SIMPLE_VECTOR_SET (v, k, obj);
     }
+  else if (SCM_I_WVECTP (v))
+    scm_c_weak_vector_set_x (v, k, obj);
   else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
     {
       scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
       SCM vv = SCM_I_ARRAY_V (v);
-      if (SCM_I_IS_VECTOR (vv))
-       {
-         if (k >= dim->ubnd - dim->lbnd + 1)
-           scm_out_of_range (NULL, scm_from_size_t (k));
-         k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
-         (SCM_I_VECTOR_WELTS (vv))[k] = obj;
-
-         if (SCM_I_WVECTP (vv))
-           {
-             /* Make it a weak pointer.  */
-             GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (vv))[k]);
-             SCM_I_REGISTER_DISAPPEARING_LINK (link,
-                                                (GC_PTR) SCM2PTR (obj));
-           }
-       }
+
+      k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
+      if (k >= dim->ubnd - dim->lbnd + 1)
+        scm_out_of_range (NULL, scm_from_size_t (k));
+
+      if (SCM_I_IS_NONWEAK_VECTOR (vv))
+        SCM_SIMPLE_VECTOR_SET (vv, k, obj);
+      else if (SCM_I_WVECTP (vv))
+        scm_c_weak_vector_set_x (vv, k, obj);
       else
        scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
     }
@@ -339,28 +313,17 @@ SCM
 scm_c_make_vector (size_t k, SCM fill)
 #define FUNC_NAME s_scm_make_vector
 {
-  SCM *vector;
-
-  vector = (SCM *)
-    scm_gc_malloc ((k + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM),
-                  "vector");
+  SCM vector;
+  unsigned long int j;
 
-  if (k > 0)
-    {
-      SCM *base;
-      unsigned long int j;
-
-      SCM_ASSERT_RANGE (1, scm_from_ulong (k), k <= VECTOR_MAX_LENGTH);
+  SCM_ASSERT_RANGE (1, scm_from_size_t (k), k <= VECTOR_MAX_LENGTH);
 
-      base = vector + SCM_I_VECTOR_HEADER_SIZE;
-      for (j = 0; j != k; ++j)
-       base[j] = fill;
-    }
+  vector = scm_words ((k << 8) | scm_tc7_vector, k + 1);
 
-  ((scm_t_bits *) vector)[0] = (k << 8) | scm_tc7_vector;
-  ((scm_t_bits *) vector)[1] = 0;
+  for (j = 0; j < k; ++j)
+    SCM_SIMPLE_VECTOR_SET (vector, j, fill);
 
-  return PTR2SCM (vector);
+  return vector;
 }
 #undef FUNC_NAME
 
@@ -389,72 +352,6 @@ SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
 #undef FUNC_NAME
 
 
-/* Weak vectors.  */
-
-/* Allocate memory for the elements of a weak vector on behalf of the
-   caller.  */
-static SCM
-make_weak_vector (scm_t_bits type, size_t c_size)
-{
-  SCM *vector;
-  size_t total_size;
-
-  total_size = (c_size + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM);
-  vector = (SCM *) scm_gc_malloc_pointerless (total_size, "weak vector");
-
-  ((scm_t_bits *) vector)[0] = (c_size << 8) | scm_tc7_wvect;
-  ((scm_t_bits *) vector)[1] = type;
-
-  return PTR2SCM (vector);
-}
-
-/* Return a new weak vector.  The allocated vector will be of the given weak
-   vector subtype.  It will contain SIZE elements which are initialized with
-   the FILL object, or, if FILL is undefined, with an unspecified object.  */
-SCM
-scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill)
-{
-  SCM wv, *base;
-  size_t c_size, j;
-
-  if (SCM_UNBNDP (fill))
-    fill = SCM_UNSPECIFIED;
-
-  c_size = scm_to_unsigned_integer (size, 0, VECTOR_MAX_LENGTH);
-  wv = make_weak_vector (type, c_size);
-  base = SCM_I_WVECT_GC_WVELTS (wv);
-
-  for (j = 0; j != c_size; ++j)
-    base[j] = fill;
-
-  return wv;
-}
-
-/* Return a new weak vector with type TYPE and whose content are taken from
-   list LST.  */
-SCM
-scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst)
-{
-  SCM wv, *elt;
-  long c_size;
-
-  c_size = scm_ilength (lst);
-  SCM_ASSERT (c_size >= 0, lst, SCM_ARG2, "scm_i_make_weak_vector_from_list");
-
-  wv = make_weak_vector(type, (size_t) c_size);
-
-  for (elt = SCM_I_WVECT_GC_WVELTS (wv);
-       scm_is_pair (lst);
-       lst = SCM_CDR (lst), elt++)
-    {
-      *elt = SCM_CAR (lst);
-    }
-
-  return wv;
-}
-
-
-
 SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0, 
            (SCM v),
            "Return a newly allocated list composed of the elements of 
@var{v}.\n"
diff --git a/libguile/vectors.h b/libguile/vectors.h
index 3746e90..fd69a1c 100644
--- a/libguile/vectors.h
+++ b/libguile/vectors.h
@@ -3,7 +3,7 @@
 #ifndef SCM_VECTORS_H
 #define SCM_VECTORS_H
 
-/* Copyright (C) 1995,1996,1998,2000,2001,2002,2004,2005, 2006, 2008, 2009 
Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001,2002,2004,2005, 2006, 2008, 2009, 
2011 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -63,31 +63,14 @@ SCM_API SCM *scm_vector_writable_elements (SCM vec,
 
 /* Internals */
 
-/* Vectors have a 2-word header: 1 for the type tag, and 1 for the weak
-   vector extra data (see below.)  */
-#define SCM_I_VECTOR_HEADER_SIZE  2U
-
 #define SCM_I_IS_VECTOR(x)     (!SCM_IMP(x) && (SCM_TYP7S(x)==scm_tc7_vector))
 #define SCM_I_IS_NONWEAK_VECTOR(x) (!SCM_IMP(x) && 
(SCM_TYP7(x)==scm_tc7_vector))
 #define SCM_I_VECTOR_ELTS(x)   ((const SCM *) SCM_I_VECTOR_WELTS (x))
-#define SCM_I_VECTOR_WELTS(x)  (SCM_CELL_OBJECT_LOC (x, 
SCM_I_VECTOR_HEADER_SIZE))
+#define SCM_I_VECTOR_WELTS(x)  (SCM_CELL_OBJECT_LOC (x, 1))
 #define SCM_I_VECTOR_LENGTH(x) (((size_t) SCM_CELL_WORD_0 (x)) >> 8)
 
 SCM_INTERNAL SCM  scm_i_vector_equal_p (SCM x, SCM y);
 
-/* Weak vectors share implementation details with ordinary vectors,
-   but no one else should.  */
-
-#define SCM_I_WVECTP(x)                 (!SCM_IMP (x) && \
-                                         SCM_TYP7 (x) == scm_tc7_wvect)
-#define SCM_I_WVECT_LENGTH              SCM_I_VECTOR_LENGTH
-#define SCM_I_WVECT_VELTS               SCM_I_VECTOR_ELTS
-#define SCM_I_WVECT_GC_WVELTS           SCM_I_VECTOR_WELTS
-#define SCM_I_WVECT_EXTRA(x)            (SCM_CELL_WORD_1 (x))
-#define SCM_I_SET_WVECT_EXTRA(x, t)     (SCM_SET_CELL_WORD_1 ((x),(t)))
-
-SCM_INTERNAL SCM scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill);
-SCM_INTERNAL SCM scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst);
 
 SCM_INTERNAL void scm_init_vectors (void);
 
diff --git a/libguile/weak-table.c b/libguile/weak-table.c
new file mode 100644
index 0000000..160eca2
--- /dev/null
+++ b/libguile/weak-table.c
@@ -0,0 +1,1134 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+
+#include "libguile/bdw-gc.h"
+#include <gc/gc_mark.h>
+
+#include "libguile/_scm.h"
+#include "libguile/hash.h"
+#include "libguile/eval.h"
+#include "libguile/ports.h"
+
+#include "libguile/validate.h"
+#include "libguile/weak-table.h"
+
+
+/* Weak Tables
+
+   This file implements weak hash tables.  Weak hash tables are
+   generally used when you want to augment some object with additional
+   data, but when you don't have space to store the data in the object.
+   For example, procedure properties are implemented with weak tables.
+
+   Weak tables are implemented using an open-addressed hash table.
+   Basically this means that there is an array of entries, and the item
+   is expected to be found the slot corresponding to its hash code,
+   modulo the length of the array.
+
+   Collisions are handled using linear probing with the Robin Hood
+   technique.  See Pedro Celis' paper, "Robin Hood Hashing":
+
+     http://www.cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf
+
+   The vector of entries is allocated in such a way that the GC doesn't
+   trace the weak values.  For doubly-weak tables, this means that the
+   entries are allocated as an "atomic" piece of memory.  Key-weak and
+   value-weak tables use a special GC kind with a custom mark procedure.
+   When items are added weakly into table, a disappearing link is
+   registered to their locations.  If the referent is collected, then
+   that link will be zeroed out.
+
+   An entry in the table consists of the key and the value, together
+   with the hash code of the key.  We munge hash codes so that they are
+   never 0.  In this way we can detect removed entries (key of zero but
+   nonzero hash code), and can then reshuffle elements as needed to
+   maintain the robin hood ordering.
+
+   Compared to buckets-and-chains hash tables, open addressing has the
+   advantage that it is very cache-friendly.  It also uses less memory.
+
+   Implementation-wise, there are two things to note.
+
+     1. We assume that hash codes are evenly distributed across the
+        range of unsigned longs.  The actual hash code stored in the
+        entry is left-shifted by 1 bit (losing 1 bit of hash precision),
+        and then or'd with 1.  In this way we ensure that the hash field
+        of an occupied entry is nonzero.  To map to an index, we
+        right-shift the hash by one, divide by the size, and take the
+        remainder.
+
+     2. Since the weak references are stored in an atomic region with
+        disappearing links, they need to be accessed with the GC alloc
+        lock.  `copy_weak_entry' will do that for you.  The hash code
+        itself can be read outside the lock, though.
+  */
+
+
+typedef struct {
+  unsigned long hash;
+  scm_t_bits key;
+  scm_t_bits value;
+} scm_t_weak_entry;
+
+
+struct weak_entry_data {
+  scm_t_weak_entry *in;
+  scm_t_weak_entry *out;
+};
+  
+static void*
+do_copy_weak_entry (void *data)
+{
+  struct weak_entry_data *e = data;
+
+  e->out->hash = e->in->hash;
+  e->out->key = e->in->key;
+  e->out->value = e->in->value;
+
+  return NULL;
+}
+
+static void
+copy_weak_entry (scm_t_weak_entry *src, scm_t_weak_entry *dst)
+{
+  struct weak_entry_data data;
+
+  data.in = src;
+  data.out = dst;
+      
+  GC_call_with_alloc_lock (do_copy_weak_entry, &data);
+}
+  
+static void
+register_disappearing_links (scm_t_weak_entry *entry,
+                             SCM k, SCM v,
+                             scm_t_weak_table_kind kind)
+{
+  if (SCM_UNPACK (k) && SCM_NIMP (k)
+      && (kind == SCM_WEAK_TABLE_KIND_KEY
+          || kind == SCM_WEAK_TABLE_KIND_BOTH))
+    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &entry->key,
+                                      (GC_PTR) SCM2PTR (k));
+
+  if (SCM_UNPACK (v) && SCM_NIMP (v)
+      && (kind == SCM_WEAK_TABLE_KIND_VALUE
+          || kind == SCM_WEAK_TABLE_KIND_BOTH))
+    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &entry->value,
+                                      (GC_PTR) SCM2PTR (v));
+}
+
+static void
+unregister_disappearing_links (scm_t_weak_entry *entry,
+                               scm_t_weak_table_kind kind)
+{
+  if (kind == SCM_WEAK_TABLE_KIND_KEY || kind == SCM_WEAK_TABLE_KIND_BOTH)
+    GC_unregister_disappearing_link ((GC_PTR) &entry->key);
+
+  if (kind == SCM_WEAK_TABLE_KIND_VALUE || kind == SCM_WEAK_TABLE_KIND_BOTH)
+    GC_unregister_disappearing_link ((GC_PTR) &entry->value);
+}
+
+static void
+move_weak_entry (scm_t_weak_entry *from, scm_t_weak_entry *to,
+                 scm_t_weak_table_kind kind)
+{
+  if (from->hash)
+    {
+      scm_t_weak_entry copy;
+      
+      copy_weak_entry (from, &copy);
+      to->hash = copy.hash;
+      to->key = copy.key;
+      to->value = copy.value;
+
+      unregister_disappearing_links (from, kind);
+      register_disappearing_links (to,
+                                   SCM_PACK (copy.key), SCM_PACK (copy.value),
+                                   kind);
+    }
+  else
+    {
+      to->hash = 0;
+      to->key = 0;
+      to->value = 0;
+    }
+}
+
+
+typedef struct {
+  scm_t_weak_entry *entries;    /* the data */
+  scm_i_pthread_mutex_t lock;   /* the lock */
+  scm_t_weak_table_kind kind;   /* what kind of table it is */
+  unsigned long size;          /* total number of slots. */
+  unsigned long n_items;       /* number of items in table */
+  unsigned long lower;         /* when to shrink */
+  unsigned long upper;         /* when to grow */
+  int size_index;              /* index into hashtable_size */
+  int min_size_index;          /* minimum size_index */
+} scm_t_weak_table;
+
+
+#define SCM_WEAK_TABLE_P(x) (!SCM_IMP (x) && SCM_TYP7(x) == scm_tc7_weak_table)
+#define SCM_VALIDATE_WEAK_TABLE(pos, arg) \
+  SCM_MAKE_VALIDATE_MSG (pos, arg, WEAK_TABLE_P, "weak-table")
+#define SCM_WEAK_TABLE(x) ((scm_t_weak_table *) SCM_CELL_WORD_1 (x))
+
+
+static unsigned long
+hash_to_index (unsigned long hash, unsigned long size)
+{
+  return (hash >> 1) % size;
+}
+
+static unsigned long
+entry_distance (unsigned long hash, unsigned long k, unsigned long size)
+{
+  unsigned long origin = hash_to_index (hash, size);
+
+  if (k >= origin)
+    return k - origin;
+  else
+    /* The other key was displaced and wrapped around.  */
+    return size - origin + k;
+}
+
+static void
+rob_from_rich (scm_t_weak_table *table, unsigned long k)
+{
+  unsigned long empty, size;
+
+  size = table->size;
+
+  /* If we are to free up slot K in the table, we need room to do so.  */
+  assert (table->n_items < size);
+  
+  empty = k;
+  do 
+    empty = (empty + 1) % size;
+  while (table->entries[empty].hash);
+
+  do
+    {
+      unsigned long last = empty ? (empty - 1) : (size - 1);
+      move_weak_entry (&table->entries[last], &table->entries[empty],
+                       table->kind);
+      empty = last;
+    }
+  while (empty != k);
+
+  table->entries[empty].hash = 0;
+  table->entries[empty].key = 0;
+  table->entries[empty].value = 0;
+}
+
+static void
+give_to_poor (scm_t_weak_table *table, unsigned long k)
+{
+  /* Slot K was just freed up; possibly shuffle others down.  */
+  unsigned long size = table->size;
+
+  while (1)
+    {
+      unsigned long next = (k + 1) % size;
+      unsigned long hash;
+      scm_t_weak_entry copy;
+
+      hash = table->entries[next].hash;
+
+      if (!hash || hash_to_index (hash, size) == next)
+        break;
+
+      copy_weak_entry (&table->entries[next], &copy);
+
+      if (!copy.key || !copy.value)
+        /* Lost weak reference.  */
+        {
+          give_to_poor (table, next);
+          table->n_items--;
+          continue;
+        }
+
+      move_weak_entry (&table->entries[next], &table->entries[k],
+                       table->kind);
+
+      k = next;
+    }
+
+  /* We have shuffled down any entries that should be shuffled down; now
+     free the end.  */
+  table->entries[k].hash = 0;
+  table->entries[k].key = 0;
+  table->entries[k].value = 0;
+}
+
+
+
+
+/* The GC "kinds" for singly-weak tables.  */
+static int weak_key_gc_kind;
+static int weak_value_gc_kind;
+
+static struct GC_ms_entry *
+mark_weak_key_table (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
+                     struct GC_ms_entry *mark_stack_limit, GC_word env)
+{
+  scm_t_weak_entry *entries = (scm_t_weak_entry*) addr;
+  unsigned long k, size = GC_size (addr) / sizeof (scm_t_weak_entry);
+
+  for (k = 0; k < size; k++)
+    if (entries[k].hash && entries[k].key)
+      {
+        SCM value = SCM_PACK (entries[k].value);
+        mark_stack_ptr = GC_MARK_AND_PUSH ((GC_word*) SCM2PTR (value),
+                                           mark_stack_ptr, mark_stack_limit,
+                                           NULL);
+      }
+
+  return mark_stack_ptr;
+}
+
+static struct GC_ms_entry *
+mark_weak_value_table (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
+                       struct GC_ms_entry *mark_stack_limit, GC_word env)
+{
+  scm_t_weak_entry *entries = (scm_t_weak_entry*) addr;
+  unsigned long k, size = GC_size (addr) / sizeof (scm_t_weak_entry);
+
+  for (k = 0; k < size; k++)
+    if (entries[k].hash && entries[k].value)
+      {
+        SCM key = SCM_PACK (entries[k].key);
+        mark_stack_ptr = GC_MARK_AND_PUSH ((GC_word*) SCM2PTR (key),
+                                           mark_stack_ptr, mark_stack_limit,
+                                           NULL);
+      }
+
+  return mark_stack_ptr;
+}
+
+static scm_t_weak_entry *
+allocate_entries (unsigned long size, scm_t_weak_table_kind kind)
+{
+  scm_t_weak_entry *ret;
+  size_t bytes = size * sizeof (*ret);
+
+  switch (kind)
+    {
+    case SCM_WEAK_TABLE_KIND_KEY:
+      ret = GC_generic_malloc (bytes, weak_key_gc_kind);
+      break;
+    case SCM_WEAK_TABLE_KIND_VALUE:
+      ret = GC_generic_malloc (bytes, weak_value_gc_kind);
+      break;
+    case SCM_WEAK_TABLE_KIND_BOTH:
+      ret = scm_gc_malloc_pointerless (bytes, "weak-table");
+      break;
+    default:
+      abort ();
+    }
+
+  memset (ret, 0, bytes);
+
+  return ret;
+}
+
+
+
+/* Growing or shrinking is triggered when the load factor
+ *
+ *   L = N / S    (N: number of items in table, S: bucket vector length)
+ *
+ * passes an upper limit of 0.9 or a lower limit of 0.2.
+ *
+ * The implementation stores the upper and lower number of items which
+ * trigger a resize in the hashtable object.
+ *
+ * Possible hash table sizes (primes) are stored in the array
+ * hashtable_size.
+ */
+
+static unsigned long hashtable_size[] = {
+  31, 61, 113, 223, 443, 883, 1759, 3517, 7027, 14051, 28099, 56197, 112363,
+  224717, 449419, 898823, 1797641, 3595271, 7190537, 14381041, 28762081,
+  57524111, 115048217, 230096423
+};
+
+#define HASHTABLE_SIZE_N (sizeof(hashtable_size)/sizeof(unsigned long))
+
+static void
+resize_table (scm_t_weak_table *table)
+{
+  scm_t_weak_entry *old_entries, *new_entries;
+  int i;
+  unsigned long old_size, new_size, old_k;
+
+  old_entries = table->entries;
+  old_size = table->size;
+  
+  if (table->n_items < table->lower)
+    {
+      /* rehashing is not triggered when i <= min_size */
+      i = table->size_index;
+      do
+       --i;
+      while (i > table->min_size_index
+            && table->n_items < hashtable_size[i] / 4);
+    }
+  else
+    {
+      i = table->size_index + 1;
+      if (i >= HASHTABLE_SIZE_N)
+        /* The biggest size currently is 230096423, which for a 32-bit
+           machine will occupy 2.3GB of memory at a load of 80%.  There
+           is probably something better to do here, but if you have a
+           weak map of that size, you are hosed in any case.  */
+        abort ();
+    }
+
+  new_size = hashtable_size[i];
+  new_entries = allocate_entries (new_size, table->kind);
+
+  table->size_index = i;
+  table->size = new_size;
+  if (i <= table->min_size_index)
+    table->lower = 0;
+  else
+    table->lower = new_size / 5;
+  table->upper = 9 * new_size / 10;
+  table->n_items = 0;
+  table->entries = new_entries;
+
+  for (old_k = 0; old_k < old_size; old_k++)
+    {
+      scm_t_weak_entry copy;
+      unsigned long new_k, distance;
+
+      if (!old_entries[old_k].hash)
+        continue;
+      
+      copy_weak_entry (&old_entries[old_k], &copy);
+      
+      if (!copy.key || !copy.value)
+        continue;
+      
+      new_k = hash_to_index (copy.hash, new_size);
+
+      for (distance = 0; ; distance++, new_k = (new_k + 1) % new_size)
+        {
+          unsigned long other_hash = new_entries[new_k].hash;
+
+          if (!other_hash)
+            /* Found an empty entry. */
+            break;
+
+          /* Displace the entry if our distance is less, otherwise keep
+             looking. */
+          if (entry_distance (other_hash, new_k, new_size) < distance)
+            {
+              rob_from_rich (table, new_k);
+              break;
+            }
+        }
+          
+      table->n_items++;
+      new_entries[new_k].hash = copy.hash;
+      new_entries[new_k].key = copy.key;
+      new_entries[new_k].value = copy.value;
+
+      register_disappearing_links (&new_entries[new_k],
+                                   SCM_PACK (copy.key), SCM_PACK (copy.value),
+                                   table->kind);
+    }
+}
+
+/* Run after GC via do_vacuum_weak_table, this function runs over the
+   whole table, removing lost weak references, reshuffling the table as it
+   goes.  It might resize the table if it reaps enough entries.  */
+static void
+vacuum_weak_table (scm_t_weak_table *table)
+{
+  scm_t_weak_entry *entries = table->entries;
+  unsigned long size = table->size;
+  unsigned long k;
+
+  for (k = 0; k < size; k++)
+    {
+      unsigned long hash = entries[k].hash;
+      
+      if (hash)
+        {
+          scm_t_weak_entry copy;
+
+          copy_weak_entry (&entries[k], &copy);
+
+          if (!copy.key || !copy.value)
+            /* Lost weak reference; reshuffle.  */
+            {
+              give_to_poor (table, k);
+              table->n_items--;
+            }
+        }
+    }
+
+  if (table->n_items < table->lower)
+    resize_table (table);
+}
+
+
+
+
+static SCM
+weak_table_ref (scm_t_weak_table *table, unsigned long hash,
+                scm_t_table_predicate_fn pred, void *closure,
+                SCM dflt)
+{
+  unsigned long k, distance, size;
+  scm_t_weak_entry *entries;
+  
+  size = table->size;
+  entries = table->entries;
+
+  hash = (hash << 1) | 0x1;
+  k = hash_to_index (hash, size);
+  
+  for (distance = 0; distance < size; distance++, k = (k + 1) % size)
+    {
+      unsigned long other_hash;
+
+    retry:
+      other_hash = entries[k].hash;
+
+      if (!other_hash)
+        /* Not found. */
+        return dflt;
+
+      if (hash == other_hash)
+        {
+          scm_t_weak_entry copy;
+          
+          copy_weak_entry (&entries[k], &copy);
+
+          if (!copy.key || !copy.value)
+            /* Lost weak reference; reshuffle.  */
+            {
+              give_to_poor (table, k);
+              table->n_items--;
+              goto retry;
+            }
+
+          if (pred (SCM_PACK (copy.key), SCM_PACK (copy.value), closure))
+            /* Found. */
+            return SCM_PACK (copy.value);
+        }
+
+      /* If the entry's distance is less, our key is not in the table.  */
+      if (entry_distance (other_hash, k, size) < distance)
+        return dflt;
+    }
+
+  /* If we got here, then we were unfortunate enough to loop through the
+     whole table.  Shouldn't happen, but hey.  */
+  return dflt;
+}
+
+
+static void
+weak_table_put_x (scm_t_weak_table *table, unsigned long hash,
+                  scm_t_table_predicate_fn pred, void *closure,
+                  SCM key, SCM value)
+{
+  unsigned long k, distance, size;
+  scm_t_weak_entry *entries;
+  
+  size = table->size;
+  entries = table->entries;
+
+  hash = (hash << 1) | 0x1;
+  k = hash_to_index (hash, size);
+
+  for (distance = 0; ; distance++, k = (k + 1) % size)
+    {
+      unsigned long other_hash;
+
+    retry:
+      other_hash = entries[k].hash;
+
+      if (!other_hash)
+        /* Found an empty entry. */
+        break;
+
+      if (other_hash == hash)
+        {
+          scm_t_weak_entry copy;
+
+          copy_weak_entry (&entries[k], &copy);
+          
+          if (!copy.key || !copy.value)
+            /* Lost weak reference; reshuffle.  */
+            {
+              give_to_poor (table, k);
+              table->n_items--;
+              goto retry;
+            }
+
+          if (pred (SCM_PACK (copy.key), SCM_PACK (copy.value), closure))
+            /* Found an entry with this key. */
+            break;
+        }
+
+      if (table->n_items > table->upper)
+        /* Full table, time to resize.  */
+        {
+          resize_table (table);
+          return weak_table_put_x (table, hash >> 1, pred, closure, key, 
value);
+        }
+
+      /* Displace the entry if our distance is less, otherwise keep
+         looking. */
+      if (entry_distance (other_hash, k, size) < distance)
+        {
+          rob_from_rich (table, k);
+          break;
+        }
+    }
+          
+  if (entries[k].hash)
+    unregister_disappearing_links (&entries[k], table->kind);
+  else
+    table->n_items++;
+
+  entries[k].hash = hash;
+  entries[k].key = SCM_UNPACK (key);
+  entries[k].value = SCM_UNPACK (value);
+
+  register_disappearing_links (&entries[k], key, value, table->kind);
+}
+
+
+static void
+weak_table_remove_x (scm_t_weak_table *table, unsigned long hash,
+                   scm_t_table_predicate_fn pred, void *closure)
+{
+  unsigned long k, distance, size;
+  scm_t_weak_entry *entries;
+  
+  size = table->size;
+  entries = table->entries;
+
+  hash = (hash << 1) | 0x1;
+  k = hash_to_index (hash, size);
+
+  for (distance = 0; distance < size; distance++, k = (k + 1) % size)
+    {
+      unsigned long other_hash;
+
+    retry:
+      other_hash = entries[k].hash;
+
+      if (!other_hash)
+        /* Not found. */
+        return;
+
+      if (other_hash == hash)
+        {
+          scm_t_weak_entry copy;
+      
+          copy_weak_entry (&entries[k], &copy);
+          
+          if (!copy.key || !copy.value)
+            /* Lost weak reference; reshuffle.  */
+            {
+              give_to_poor (table, k);
+              table->n_items--;
+              goto retry;
+            }
+
+          if (pred (SCM_PACK (copy.key), SCM_PACK (copy.value), closure))
+            /* Found an entry with this key. */
+            {
+              entries[k].hash = 0;
+              entries[k].key = 0;
+              entries[k].value = 0;
+
+              unregister_disappearing_links (&entries[k], table->kind);
+
+              if (--table->n_items < table->lower)
+                resize_table (table);
+              else
+                give_to_poor (table, k);
+
+              return;
+            }
+        }
+
+      /* If the entry's distance is less, our key is not in the table.  */
+      if (entry_distance (other_hash, k, size) < distance)
+        return;
+    }
+}
+
+
+
+static SCM
+make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
+{
+  scm_t_weak_table *table;
+
+  int i = 0, n = k ? k : 31;
+  while (i + 1 < HASHTABLE_SIZE_N && n > hashtable_size[i])
+    ++i;
+  n = hashtable_size[i];
+
+  table = scm_gc_malloc (sizeof (*table), "weak-table");
+  table->entries = allocate_entries (n, kind);
+  table->kind = kind;
+  table->n_items = 0;
+  table->size = n;
+  table->lower = 0;
+  table->upper = 9 * n / 10;
+  table->size_index = i;
+  table->min_size_index = i;
+  scm_i_pthread_mutex_init (&table->lock, NULL);
+
+  return scm_cell (scm_tc7_weak_table, (scm_t_bits)table);
+}
+
+void
+scm_i_weak_table_print (SCM exp, SCM port, scm_print_state *pstate)
+{
+  scm_puts ("#<", port);
+  scm_puts ("weak-table ", port);
+  scm_uintprint (SCM_WEAK_TABLE (exp)->n_items, 10, port);
+  scm_putc ('/', port);
+  scm_uintprint (SCM_WEAK_TABLE (exp)->size, 10, port);
+  scm_puts (">", port);
+}
+
+static void
+do_vacuum_weak_table (SCM table)
+{
+  scm_t_weak_table *t;
+
+  t = SCM_WEAK_TABLE (table);
+
+  if (scm_i_pthread_mutex_trylock (&t->lock) == 0)
+    {
+      vacuum_weak_table (t);
+      scm_i_pthread_mutex_unlock (&t->lock);
+    }
+
+  return;
+}
+
+/* The before-gc C hook only runs if GC_table_start_callback is available,
+   so if not, fall back on a finalizer-based implementation.  */
+static int
+weak_gc_callback (void **weak)
+{
+  void *val = weak[0];
+  void (*callback) (SCM) = weak[1];
+  
+  if (!val)
+    return 0;
+  
+  callback (PTR2SCM (val));
+
+  return 1;
+}
+
+#ifdef HAVE_GC_TABLE_START_CALLBACK
+static void*
+weak_gc_hook (void *hook_data, void *fn_data, void *data)
+{
+  if (!weak_gc_callback (fn_data))
+    scm_c_hook_remove (&scm_before_gc_c_hook, weak_gc_hook, fn_data);
+
+  return NULL;
+}
+#else
+static void
+weak_gc_finalizer (void *ptr, void *data)
+{
+  if (weak_gc_callback (ptr))
+    GC_REGISTER_FINALIZER_NO_ORDER (ptr, weak_gc_finalizer, data, NULL, NULL);
+}
+#endif
+
+static void
+scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM))
+{
+  void **weak = GC_MALLOC_ATOMIC (sizeof (void*) * 2);
+
+  weak[0] = SCM2PTR (obj);
+  weak[1] = (void*)callback;
+  GC_GENERAL_REGISTER_DISAPPEARING_LINK (weak, SCM2PTR (obj));
+
+#ifdef HAVE_GC_TABLE_START_CALLBACK
+  scm_c_hook_add (&scm_after_gc_c_hook, weak_gc_hook, weak, 0);
+#else
+  GC_REGISTER_FINALIZER_NO_ORDER (weak, weak_gc_finalizer, NULL, NULL, NULL);
+#endif
+}
+
+SCM
+scm_c_make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
+{
+  SCM ret;
+
+  ret = make_weak_table (k, kind);
+
+  scm_c_register_weak_gc_callback (ret, do_vacuum_weak_table);
+
+  return ret;
+}
+
+SCM
+scm_weak_table_p (SCM obj)
+{
+  return scm_from_bool (SCM_WEAK_TABLE_P (obj));
+}
+
+SCM
+scm_c_weak_table_ref (SCM table, unsigned long raw_hash,
+                      scm_t_table_predicate_fn pred,
+                      void *closure, SCM dflt)
+#define FUNC_NAME "weak-table-ref"
+{
+  SCM ret;
+  scm_t_weak_table *t;
+
+  SCM_VALIDATE_WEAK_TABLE (1, table);
+
+  t = SCM_WEAK_TABLE (table);
+
+  scm_i_pthread_mutex_lock (&t->lock);
+
+  ret = weak_table_ref (t, raw_hash, pred, closure, dflt);
+
+  scm_i_pthread_mutex_unlock (&t->lock);
+
+  return ret;
+}
+#undef FUNC_NAME
+
+void
+scm_c_weak_table_put_x (SCM table, unsigned long raw_hash,
+                        scm_t_table_predicate_fn pred,
+                        void *closure, SCM key, SCM value)
+#define FUNC_NAME "weak-table-put!"
+{
+  scm_t_weak_table *t;
+
+  SCM_VALIDATE_WEAK_TABLE (1, table);
+
+  t = SCM_WEAK_TABLE (table);
+
+  scm_i_pthread_mutex_lock (&t->lock);
+
+  weak_table_put_x (t, raw_hash, pred, closure, key, value);
+
+  scm_i_pthread_mutex_unlock (&t->lock);
+}
+#undef FUNC_NAME
+
+void
+scm_c_weak_table_remove_x (SCM table, unsigned long raw_hash,
+                           scm_t_table_predicate_fn pred,
+                           void *closure)
+#define FUNC_NAME "weak-table-remove!"
+{
+  scm_t_weak_table *t;
+
+  SCM_VALIDATE_WEAK_TABLE (1, table);
+
+  t = SCM_WEAK_TABLE (table);
+
+  scm_i_pthread_mutex_lock (&t->lock);
+
+  weak_table_remove_x (t, raw_hash, pred, closure);
+
+  scm_i_pthread_mutex_unlock (&t->lock);
+}
+#undef FUNC_NAME
+
+static int
+assq_predicate (SCM x, SCM y, void *closure)
+{
+  return scm_is_eq (x, PTR2SCM (closure));
+}
+
+SCM
+scm_weak_table_refq (SCM table, SCM key, SCM dflt)
+{
+  if (SCM_UNBNDP (dflt))
+    dflt = SCM_BOOL_F;
+  
+  return scm_c_weak_table_ref (table, scm_ihashq (key, -1),
+                               assq_predicate, SCM2PTR (key),
+                               dflt);
+}
+
+SCM
+scm_weak_table_putq_x (SCM table, SCM key, SCM value)
+{
+  scm_c_weak_table_put_x (table, scm_ihashq (key, -1),
+                          assq_predicate, SCM2PTR (key),
+                          key, value);
+  return SCM_UNSPECIFIED;
+}
+
+SCM
+scm_weak_table_remq_x (SCM table, SCM key)
+{
+  scm_c_weak_table_remove_x (table, scm_ihashq (key, -1),
+                             assq_predicate, SCM2PTR (key));
+  return SCM_UNSPECIFIED;
+}
+
+SCM
+scm_weak_table_clear_x (SCM table)
+#define FUNC_NAME "weak-table-clear!"
+{
+  scm_t_weak_table *t;
+
+  SCM_VALIDATE_WEAK_TABLE (1, table);
+
+  t = SCM_WEAK_TABLE (table);
+
+  scm_i_pthread_mutex_lock (&t->lock);
+
+  memset (t->entries, 0, sizeof (scm_t_weak_entry) * t->size);
+  t->n_items = 0;
+
+  scm_i_pthread_mutex_unlock (&t->lock);
+
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM
+scm_c_weak_table_fold (scm_t_table_fold_fn proc, void *closure,
+                       SCM init, SCM table)
+{
+  scm_t_weak_table *t;
+  scm_t_weak_entry *entries;
+  unsigned long k, size;
+
+  t = SCM_WEAK_TABLE (table);
+
+  scm_i_pthread_mutex_lock (&t->lock);
+
+  size = t->size;
+  entries = t->entries;
+
+  for (k = 0; k < size; k++)
+    {
+      if (entries[k].hash)
+        {
+          scm_t_weak_entry copy;
+          
+          copy_weak_entry (&entries[k], &copy);
+      
+          if (copy.key && copy.value)
+            {
+              /* Release table lock while we call the function.  */
+              scm_i_pthread_mutex_unlock (&t->lock);
+              init = proc (closure,
+                           SCM_PACK (copy.key), SCM_PACK (copy.value),
+                           init);
+              scm_i_pthread_mutex_lock (&t->lock);
+            }
+        }
+    }
+  
+  scm_i_pthread_mutex_unlock (&t->lock);
+  
+  return init;
+}
+
+static SCM
+fold_trampoline (void *closure, SCM k, SCM v, SCM init)
+{
+  return scm_call_3 (PTR2SCM (closure), k, v, init);
+}
+
+SCM
+scm_weak_table_fold (SCM proc, SCM init, SCM table)
+#define FUNC_NAME "weak-table-fold"
+{
+  SCM_VALIDATE_WEAK_TABLE (3, table);
+  SCM_VALIDATE_PROC (1, proc);
+
+  return scm_c_weak_table_fold (fold_trampoline, SCM2PTR (proc), init, table);
+}
+#undef FUNC_NAME
+
+static SCM
+for_each_trampoline (void *closure, SCM k, SCM v, SCM seed)
+{
+  scm_call_2 (PTR2SCM (closure), k, v);
+  return seed;
+}
+
+SCM
+scm_weak_table_for_each (SCM proc, SCM table)
+#define FUNC_NAME "weak-table-for-each"
+{
+  SCM_VALIDATE_WEAK_TABLE (2, table);
+  SCM_VALIDATE_PROC (1, proc);
+
+  scm_c_weak_table_fold (for_each_trampoline, SCM2PTR (proc), SCM_BOOL_F, 
table);
+
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+static SCM
+map_trampoline (void *closure, SCM k, SCM v, SCM seed)
+{
+  return scm_cons (scm_call_2 (PTR2SCM (closure), k, v), seed);
+}
+
+SCM
+scm_weak_table_map_to_list (SCM proc, SCM table)
+#define FUNC_NAME "weak-table-map->list"
+{
+  SCM_VALIDATE_WEAK_TABLE (2, table);
+  SCM_VALIDATE_PROC (1, proc);
+
+  return scm_c_weak_table_fold (map_trampoline, SCM2PTR (proc), SCM_EOL, 
table);
+}
+#undef FUNC_NAME
+
+
+
+
+/* Legacy interface.  */
+
+SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0, 
+           (SCM n),
+           "@deffnx {Scheme Procedure} make-weak-value-hash-table size\n"
+           "@deffnx {Scheme Procedure} make-doubly-weak-hash-table size\n"
+           "Return a weak hash table with @var{size} buckets.\n"
+           "\n"
+           "You can modify weak hash tables in exactly the same way you\n"
+           "would modify regular hash tables. (@pxref{Hash Tables})")
+#define FUNC_NAME s_scm_make_weak_key_hash_table
+{
+  return scm_c_make_weak_table (SCM_UNBNDP (n) ? 0 : scm_to_ulong (n),
+                                SCM_WEAK_TABLE_KIND_KEY);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 0, 
1, 0, 
+            (SCM n),
+           "Return a hash table with weak values with @var{size} buckets.\n"
+           "(@pxref{Hash Tables})")
+#define FUNC_NAME s_scm_make_weak_value_hash_table
+{
+  return scm_c_make_weak_table (SCM_UNBNDP (n) ? 0 : scm_to_ulong (n),
+                                SCM_WEAK_TABLE_KIND_VALUE);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 
0, 0, 
+            (SCM n),
+           "Return a hash table with weak keys and values with @var{size}\n"
+           "buckets.  (@pxref{Hash Tables})")
+#define FUNC_NAME s_scm_make_doubly_weak_hash_table
+{
+  return scm_c_make_weak_table (SCM_UNBNDP (n) ? 0 : scm_to_ulong (n),
+                                SCM_WEAK_TABLE_KIND_BOTH);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_weak_key_hash_table_p, "weak-key-hash-table?", 1, 0, 0, 
+           (SCM obj),
+           "@deffnx {Scheme Procedure} weak-value-hash-table? obj\n"
+           "@deffnx {Scheme Procedure} doubly-weak-hash-table? obj\n"
+           "Return @code{#t} if @var{obj} is the specified weak hash\n"
+           "table. Note that a doubly weak hash table is neither a weak key\n"
+           "nor a weak value hash table.")
+#define FUNC_NAME s_scm_weak_key_hash_table_p
+{
+  return scm_from_bool (SCM_WEAK_TABLE_P (obj) &&
+                        SCM_WEAK_TABLE (obj)->kind == SCM_WEAK_TABLE_KIND_KEY);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_weak_value_hash_table_p, "weak-value-hash-table?", 1, 0, 0, 
+            (SCM obj),
+           "Return @code{#t} if @var{obj} is a weak value hash table.")
+#define FUNC_NAME s_scm_weak_value_hash_table_p
+{
+  return scm_from_bool (SCM_WEAK_TABLE_P (obj) &&
+                        SCM_WEAK_TABLE (obj)->kind == 
SCM_WEAK_TABLE_KIND_VALUE);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_doubly_weak_hash_table_p, "doubly-weak-hash-table?", 1, 0, 0, 
+            (SCM obj),
+           "Return @code{#t} if @var{obj} is a doubly weak hash table.")
+#define FUNC_NAME s_scm_doubly_weak_hash_table_p
+{
+  return scm_from_bool (SCM_WEAK_TABLE_P (obj) &&
+                        SCM_WEAK_TABLE (obj)->kind == 
SCM_WEAK_TABLE_KIND_BOTH);
+}
+#undef FUNC_NAME
+
+
+
+
+
+void
+scm_weak_table_prehistory (void)
+{
+  weak_key_gc_kind =
+    GC_new_kind (GC_new_free_list (),
+                GC_MAKE_PROC (GC_new_proc (mark_weak_key_table), 0),
+                0, 0);
+  weak_value_gc_kind =
+    GC_new_kind (GC_new_free_list (),
+                GC_MAKE_PROC (GC_new_proc (mark_weak_value_table), 0),
+                0, 0);
+}
+
+void
+scm_init_weak_table ()
+{
+#include "libguile/weak-table.x"
+}
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
diff --git a/libguile/weak-table.h b/libguile/weak-table.h
new file mode 100644
index 0000000..cb2831c
--- /dev/null
+++ b/libguile/weak-table.h
@@ -0,0 +1,94 @@
+/* classes: h_files */
+
+#ifndef SCM_WEAK_TABLE_H
+#define SCM_WEAK_TABLE_H
+
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+#include "libguile/__scm.h"
+
+
+
+/* The weak table API is currently only used internally.  We could make it
+   public later, after some API review.  */
+
+typedef enum {
+  SCM_WEAK_TABLE_KIND_KEY,
+  SCM_WEAK_TABLE_KIND_VALUE,
+  SCM_WEAK_TABLE_KIND_BOTH,
+} scm_t_weak_table_kind;
+
+/* Function that returns nonzero if the given mapping is the one we are
+   looking for.  */
+typedef int (*scm_t_table_predicate_fn) (SCM k, SCM v, void *closure);
+
+/* Function to fold over the elements of a set.  */
+typedef SCM (*scm_t_table_fold_fn) (void *closure, SCM k, SCM v, SCM result);
+
+SCM_INTERNAL SCM scm_c_make_weak_table (unsigned long k,
+                                        scm_t_weak_table_kind kind);
+SCM_INTERNAL SCM scm_weak_table_p (SCM h);
+
+SCM_INTERNAL SCM scm_c_weak_table_ref (SCM table, unsigned long raw_hash,
+                                       scm_t_table_predicate_fn pred,
+                                       void *closure, SCM dflt);
+SCM_INTERNAL void scm_c_weak_table_put_x (SCM table, unsigned long raw_hash,
+                                          scm_t_table_predicate_fn pred,
+                                          void *closure, SCM key, SCM value);
+SCM_INTERNAL void scm_c_weak_table_remove_x (SCM table, unsigned long raw_hash,
+                                             scm_t_table_predicate_fn pred,
+                                             void *closure);
+
+SCM_INTERNAL SCM scm_weak_table_refq (SCM table, SCM key, SCM dflt);
+SCM_INTERNAL SCM scm_weak_table_putq_x (SCM table, SCM key, SCM value);
+SCM_INTERNAL SCM scm_weak_table_remq_x (SCM table, SCM key);
+
+SCM_INTERNAL SCM scm_weak_table_clear_x (SCM table);
+
+SCM_INTERNAL SCM scm_c_weak_table_fold (scm_t_table_fold_fn proc, void 
*closure,
+                                      SCM init, SCM table);
+SCM_INTERNAL SCM scm_weak_table_fold (SCM proc, SCM init, SCM table);
+SCM_INTERNAL SCM scm_weak_table_for_each (SCM proc, SCM table);
+SCM_INTERNAL SCM scm_weak_table_map_to_list (SCM proc, SCM table);
+
+
+
+/* Legacy interface.  */
+SCM_API SCM scm_make_weak_key_hash_table (SCM k);
+SCM_API SCM scm_make_weak_value_hash_table (SCM k);
+SCM_API SCM scm_make_doubly_weak_hash_table (SCM k);
+SCM_API SCM scm_weak_key_hash_table_p (SCM h);
+SCM_API SCM scm_weak_value_hash_table_p (SCM h);
+SCM_API SCM scm_doubly_weak_hash_table_p (SCM h);
+
+
+
+SCM_INTERNAL void scm_i_weak_table_print (SCM exp, SCM port, scm_print_state 
*pstate);
+SCM_INTERNAL void scm_weak_table_prehistory (void);
+SCM_INTERNAL void scm_init_weak_table (void);
+
+#endif  /* SCM_WEAK_TABLE_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
diff --git a/libguile/weak-vector.c b/libguile/weak-vector.c
new file mode 100644
index 0000000..a42166b
--- /dev/null
+++ b/libguile/weak-vector.c
@@ -0,0 +1,207 @@
+/* Copyright (C) 1995,1996,1998,2000,2001, 2003, 2006, 2008, 2009, 2010, 2011 
Free Software Foundation, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "libguile/_scm.h"
+#include "libguile/vectors.h"
+
+#include "libguile/validate.h"
+
+
+
+/* {Weak Vectors}
+ */
+
+#define VECTOR_MAX_LENGTH (SCM_T_BITS_MAX >> 8)
+
+static SCM
+make_weak_vector (size_t len, SCM fill)
+#define FUNC_NAME "make-weak-vector"
+{
+  SCM wv;
+  size_t j;
+
+  SCM_ASSERT_RANGE (1, scm_from_size_t (len), len <= VECTOR_MAX_LENGTH);
+
+  if (SCM_UNBNDP (fill))
+    fill = SCM_UNSPECIFIED;
+
+  wv = PTR2SCM (scm_gc_malloc_pointerless ((len + 1) * sizeof (SCM),
+                                           "weak vector"));
+
+  SCM_SET_CELL_WORD_0 (wv, (len << 8) | scm_tc7_wvect);
+
+  if (SCM_NIMP (fill))
+    {
+      memset (SCM_I_VECTOR_WELTS (wv), 0, len * sizeof (SCM));
+      for (j = 0; j < len; j++)
+        scm_c_weak_vector_set_x (wv, j, fill);
+    }
+  else
+    for (j = 0; j < len; j++)
+      SCM_SIMPLE_VECTOR_SET (wv, j, fill);
+
+  return wv;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_make_weak_vector, "make-weak-vector", 1, 1, 0,
+           (SCM size, SCM fill),
+           "Return a weak vector with @var{size} elements. If the optional\n"
+           "argument @var{fill} is given, all entries in the vector will be\n"
+           "set to @var{fill}. The default value for @var{fill} is the\n"
+           "empty list.")
+#define FUNC_NAME s_scm_make_weak_vector
+{
+  return make_weak_vector (scm_to_size_t (size), fill);
+}
+#undef FUNC_NAME
+
+
+SCM_REGISTER_PROC(s_list_to_weak_vector, "list->weak-vector", 1, 0, 0, 
scm_weak_vector);
+
+SCM_DEFINE (scm_weak_vector, "weak-vector", 0, 0, 1, 
+           (SCM lst),
+           "@deffnx {Scheme Procedure} list->weak-vector lst\n"
+           "Construct a weak vector from a list: @code{weak-vector} uses\n"
+           "the list of its arguments while @code{list->weak-vector} uses\n"
+           "its only argument @var{l} (a list) to construct a weak vector\n"
+           "the same way @code{list->vector} would.")
+#define FUNC_NAME s_scm_weak_vector
+{
+  SCM wv;
+  size_t i;
+  long c_size;
+
+  SCM_VALIDATE_LIST_COPYLEN (SCM_ARG1, lst, c_size);
+
+  wv = make_weak_vector ((size_t) c_size, SCM_BOOL_F);
+
+  for (i = 0; scm_is_pair (lst); lst = SCM_CDR (lst), i++)
+    scm_c_weak_vector_set_x (wv, i, SCM_CAR (lst));
+
+  return wv;
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_weak_vector_p, "weak-vector?", 1, 0, 0, 
+           (SCM obj),
+           "Return @code{#t} if @var{obj} is a weak vector. Note that all\n"
+           "weak hashes are also weak vectors.")
+#define FUNC_NAME s_scm_weak_vector_p
+{
+  return scm_from_bool (SCM_I_WVECTP (obj));
+}
+#undef FUNC_NAME
+
+
+struct weak_vector_ref_data
+{
+  SCM wv;
+  size_t k;
+};
+
+static void*
+weak_vector_ref (void *data)
+{
+  struct weak_vector_ref_data *d = data;
+
+  return SCM_SIMPLE_VECTOR_REF (d->wv, d->k);
+}
+
+SCM
+scm_c_weak_vector_ref (SCM wv, size_t k)
+{
+  struct weak_vector_ref_data d;
+  void *ret;
+
+  d.wv = wv;
+  d.k = k;
+  
+  if (k >= SCM_I_VECTOR_LENGTH (wv))
+    scm_out_of_range (NULL, scm_from_size_t (k)); 
+
+  ret = GC_call_with_alloc_lock (weak_vector_ref, &d);
+  
+  if (ret)
+    return PTR2SCM (ret);
+  else
+    return SCM_BOOL_F;
+}
+
+
+void
+scm_c_weak_vector_set_x (SCM wv, size_t k, SCM x)
+{
+  SCM *elts;
+  struct weak_vector_ref_data d;
+  void *prev;
+
+  d.wv = wv;
+  d.k = k;
+
+  if (k >= SCM_I_VECTOR_LENGTH (wv))
+    scm_out_of_range (NULL, scm_from_size_t (k)); 
+  
+  prev = GC_call_with_alloc_lock (weak_vector_ref, &d);
+
+  elts = SCM_I_VECTOR_WELTS (wv);
+
+  if (prev && SCM_NIMP (PTR2SCM (prev)))
+    GC_unregister_disappearing_link ((GC_PTR) &elts[k]);
+  
+  elts[k] = x;
+
+  if (SCM_NIMP (x))
+    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &elts[k],
+                                      (GC_PTR) SCM2PTR (x));
+}
+
+
+
+static void
+scm_init_weak_vector_builtins (void)
+{
+#ifndef SCM_MAGIC_SNARFER
+#include "libguile/weak-vector.x"
+#endif
+}
+
+void
+scm_init_weak_vectors ()
+{
+  scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
+                            "scm_init_weak_vector_builtins",
+                            
(scm_t_extension_init_func)scm_init_weak_vector_builtins,
+                            NULL);
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
diff --git a/libguile/extensions.h b/libguile/weak-vector.h
similarity index 60%
copy from libguile/extensions.h
copy to libguile/weak-vector.h
index 765f9be..80bb414 100644
--- a/libguile/extensions.h
+++ b/libguile/weak-vector.h
@@ -1,9 +1,9 @@
 /* classes: h_files */
 
-#ifndef SCM_EXTENSIONS_H
-#define SCM_EXTENSIONS_H
+#ifndef SCM_WEAK_VECTOR_H
+#define SCM_WEAK_VECTOR_H
 
-/* Copyright (C) 2001, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,2000,2001, 2003, 2006, 2008, 2009, 2011 Free 
Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -26,18 +26,20 @@
 #include "libguile/__scm.h"
 
 
+/* Weak vectors.  */
 
-typedef void (*scm_t_extension_init_func)(void*);
+#define SCM_I_WVECTP(x) (!SCM_IMP (x) && SCM_TYP7 (x) == scm_tc7_wvect)
 
-SCM_API void scm_c_register_extension (const char *lib, const char *init,
-                                      void (*func) (void *), void *data);
+SCM_API SCM scm_make_weak_vector (SCM k, SCM fill);
+SCM_API SCM scm_weak_vector (SCM l);
+SCM_API SCM scm_weak_vector_p (SCM x);
+SCM_INTERNAL SCM scm_c_weak_vector_ref (SCM v, size_t k);
+SCM_INTERNAL void scm_c_weak_vector_set_x (SCM v, size_t k, SCM x);
 
-SCM_API void scm_c_load_extension (const char *lib, const char *init);
-SCM_API SCM scm_load_extension (SCM lib, SCM init);
+SCM_INTERNAL void scm_init_weak_vectors (void);
 
-SCM_INTERNAL void scm_init_extensions (void);
 
-#endif  /* SCM_EXTENSIONS_H */
+#endif  /* SCM_WEAK_VECTOR_H */
 
 /*
   Local Variables:
diff --git a/libguile/weaks.c b/libguile/weaks.c
deleted file mode 100644
index 92d351e..0000000
--- a/libguile/weaks.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* Copyright (C) 1995,1996,1998,2000,2001, 2003, 2006, 2008, 2009, 2010, 2011 
Free Software Foundation, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "libguile/_scm.h"
-#include "libguile/vectors.h"
-#include "libguile/hashtab.h"
-
-#include "libguile/validate.h"
-#include "libguile/weaks.h"
-
-#include "libguile/bdw-gc.h"
-#include <gc/gc_typed.h>
-
-
-
-/* Weak pairs for use in weak alist vectors and weak hash tables.
-
-   We have weal-car pairs, weak-cdr pairs, and doubly weak pairs.  In weak
-   pairs, the weak component(s) are not scanned for pointers and are
-   registered as disapperaring links; therefore, the weak component may be
-   set to NULL by the garbage collector when no other reference to that word
-   exist.  Thus, users should only access weak pairs via the
-   `SCM_WEAK_PAIR_C[AD]R ()' macros.  See also `scm_fixup_weak_alist ()' in
-   `hashtab.c'.  */
-
-/* Type descriptors for weak-c[ad]r pairs.  */
-static GC_descr wcar_pair_descr, wcdr_pair_descr;
-
-
-SCM
-scm_weak_car_pair (SCM car, SCM cdr)
-{
-  scm_t_cell *cell;
-
-  cell = (scm_t_cell *)GC_malloc_explicitly_typed (sizeof (*cell),
-                                                  wcar_pair_descr);
-
-  cell->word_0 = car;
-  cell->word_1 = cdr;
-
-  if (SCM_NIMP (car))
-    /* Weak car cells make sense iff the car is non-immediate.  */
-    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &cell->word_0,
-                                      (GC_PTR) SCM2PTR (car));
-
-  return (SCM_PACK (cell));
-}
-
-SCM
-scm_weak_cdr_pair (SCM car, SCM cdr)
-{
-  scm_t_cell *cell;
-
-  cell = (scm_t_cell *)GC_malloc_explicitly_typed (sizeof (*cell),
-                                                  wcdr_pair_descr);
-
-  cell->word_0 = car;
-  cell->word_1 = cdr;
-
-  if (SCM_NIMP (cdr))
-    /* Weak cdr cells make sense iff the cdr is non-immediate.  */
-    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &cell->word_1,
-                                      (GC_PTR) SCM2PTR (cdr));
-
-  return (SCM_PACK (cell));
-}
-
-SCM
-scm_doubly_weak_pair (SCM car, SCM cdr)
-{
-  /* Doubly weak cells shall not be scanned at all for pointers.  */
-  scm_t_cell *cell = (scm_t_cell *)scm_gc_malloc_pointerless (sizeof (*cell),
-                                                             "weak cell");
-
-  cell->word_0 = car;
-  cell->word_1 = cdr;
-
-  if (SCM_NIMP (car))
-    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &cell->word_0,
-                                      (GC_PTR) SCM2PTR (car));
-  if (SCM_NIMP (cdr))
-    SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &cell->word_1,
-                                      (GC_PTR) SCM2PTR (cdr));
-
-  return (SCM_PACK (cell));
-}
-
-
-
-
-/* 1. The current hash table implementation in hashtab.c uses weak alist
- *    vectors (formerly called weak hash tables) internally.
- *
- * 2. All hash table operations still work on alist vectors.
- *
- * 3. The weak vector and alist vector Scheme API is accessed through
- *    the module (ice-9 weak-vector).
- */
-
-
-/* {Weak Vectors}
- */
-
-
-SCM_DEFINE (scm_make_weak_vector, "make-weak-vector", 1, 1, 0,
-           (SCM size, SCM fill),
-           "Return a weak vector with @var{size} elements. If the optional\n"
-           "argument @var{fill} is given, all entries in the vector will be\n"
-           "set to @var{fill}. The default value for @var{fill} is the\n"
-           "empty list.")
-#define FUNC_NAME s_scm_make_weak_vector
-{
-  return scm_i_make_weak_vector (0, size, fill);
-}
-#undef FUNC_NAME
-
-
-SCM_REGISTER_PROC(s_list_to_weak_vector, "list->weak-vector", 1, 0, 0, 
scm_weak_vector);
-
-SCM_DEFINE (scm_weak_vector, "weak-vector", 0, 0, 1, 
-           (SCM l),
-           "@deffnx {Scheme Procedure} list->weak-vector l\n"
-           "Construct a weak vector from a list: @code{weak-vector} uses\n"
-           "the list of its arguments while @code{list->weak-vector} uses\n"
-           "its only argument @var{l} (a list) to construct a weak vector\n"
-           "the same way @code{list->vector} would.")
-#define FUNC_NAME s_scm_weak_vector
-{
-  return scm_i_make_weak_vector_from_list (0, l);
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_weak_vector_p, "weak-vector?", 1, 0, 0, 
-           (SCM obj),
-           "Return @code{#t} if @var{obj} is a weak vector. Note that all\n"
-           "weak hashes are also weak vectors.")
-#define FUNC_NAME s_scm_weak_vector_p
-{
-  return scm_from_bool (SCM_I_WVECTP (obj) && !SCM_IS_WHVEC (obj));
-}
-#undef FUNC_NAME
-
-
-/* Weak alist vectors, i.e., vectors of alists.
-
-   The alist vector themselves are _not_ weak.  The `car' (or `cdr', or both)
-   of the pairs within it are weak.  See `hashtab.c' for details.  */
-
-
-/* FIXME: We used to have two implementations of weak hash tables: the one in
-   here and the one in `hashtab.c'.  The difference is that weak alist
-   vectors could be used as vectors while (weak) hash tables can't.  We need
-   to unify that.  */
-
-SCM_DEFINE (scm_make_weak_key_alist_vector, "make-weak-key-alist-vector", 0, 
1, 0, 
-           (SCM size),
-           "@deffnx {Scheme Procedure} make-weak-value-alist-vector size\n"
-           "@deffnx {Scheme Procedure} make-doubly-weak-alist-vector size\n"
-           "Return a weak hash table with @var{size} buckets. As with any\n"
-           "hash table, choosing a good size for the table requires some\n"
-           "caution.\n"
-           "\n"
-           "You can modify weak hash tables in exactly the same way you\n"
-           "would modify regular hash tables. (@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_weak_key_alist_vector
-{
-  return scm_make_weak_key_hash_table (size);
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_make_weak_value_alist_vector, "make-weak-value-alist-vector", 
0, 1, 0, 
-            (SCM size),
-           "Return a hash table with weak values with @var{size} buckets.\n"
-           "(@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_weak_value_alist_vector
-{
-  return scm_make_weak_value_hash_table (size);
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_make_doubly_weak_alist_vector, 
"make-doubly-weak-alist-vector", 1, 0, 0, 
-            (SCM size),
-           "Return a hash table with weak keys and values with @var{size}\n"
-           "buckets.  (@pxref{Hash Tables})")
-#define FUNC_NAME s_scm_make_doubly_weak_alist_vector
-{
-  return scm_make_doubly_weak_hash_table (size);
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_weak_key_alist_vector_p, "weak-key-alist-vector?", 1, 0, 0, 
-           (SCM obj),
-           "@deffnx {Scheme Procedure} weak-value-alist-vector? obj\n"
-           "@deffnx {Scheme Procedure} doubly-weak-alist-vector? obj\n"
-           "Return @code{#t} if @var{obj} is the specified weak hash\n"
-           "table. Note that a doubly weak hash table is neither a weak key\n"
-           "nor a weak value hash table.")
-#define FUNC_NAME s_scm_weak_key_alist_vector_p
-{
-  return scm_from_bool (SCM_I_WVECTP (obj) && SCM_IS_WHVEC (obj));
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_weak_value_alist_vector_p, "weak-value-alist-vector?", 1, 0, 
0, 
-            (SCM obj),
-           "Return @code{#t} if @var{obj} is a weak value hash table.")
-#define FUNC_NAME s_scm_weak_value_alist_vector_p
-{
-  return scm_from_bool (SCM_I_WVECTP (obj) && SCM_IS_WHVEC_V (obj));
-}
-#undef FUNC_NAME
-
-
-SCM_DEFINE (scm_doubly_weak_alist_vector_p, "doubly-weak-alist-vector?", 1, 0, 
0, 
-            (SCM obj),
-           "Return @code{#t} if @var{obj} is a doubly weak hash table.")
-#define FUNC_NAME s_scm_doubly_weak_alist_vector_p
-{
-  return scm_from_bool (SCM_I_WVECTP (obj) && SCM_IS_WHVEC_B (obj));
-}
-#undef FUNC_NAME
-
-
-
-
-SCM
-scm_init_weaks_builtins ()
-{
-#include "libguile/weaks.x"
-  return SCM_UNSPECIFIED;
-}
-
-void
-scm_weaks_prehistory ()
-{
-  /* Initialize weak pairs.  */
-  GC_word wcar_pair_bitmap[GC_BITMAP_SIZE (scm_t_cell)] = { 0 };
-  GC_word wcdr_pair_bitmap[GC_BITMAP_SIZE (scm_t_cell)] = { 0 };
-
-  /* In a weak-car pair, only the second word must be scanned for
-     pointers.  */
-  GC_set_bit (wcar_pair_bitmap, GC_WORD_OFFSET (scm_t_cell, word_1));
-  wcar_pair_descr = GC_make_descriptor (wcar_pair_bitmap,
-                                       GC_WORD_LEN (scm_t_cell));
-
-  /* Conversely, in a weak-cdr pair, only the first word must be scanned for
-     pointers.  */
-  GC_set_bit (wcdr_pair_bitmap, GC_WORD_OFFSET (scm_t_cell, word_0));
-  wcdr_pair_descr = GC_make_descriptor (wcdr_pair_bitmap,
-                                       GC_WORD_LEN (scm_t_cell));
-
-}
-
-void
-scm_init_weaks ()
-{
-  scm_c_define_gsubr ("%init-weaks-builtins", 0, 0, 0,
-                     scm_init_weaks_builtins);
-}
-
-
-/*
-  Local Variables:
-  c-file-style: "gnu"
-  End:
-*/
diff --git a/libguile/weaks.h b/libguile/weaks.h
deleted file mode 100644
index fc16f8b..0000000
--- a/libguile/weaks.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* classes: h_files */
-
-#ifndef SCM_WEAKS_H
-#define SCM_WEAKS_H
-
-/* Copyright (C) 1995,1996,2000,2001, 2003, 2006, 2008, 2009, 2011 Free 
Software Foundation, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-
-
-#include "libguile/__scm.h"
-
-
-
-#define SCM_WVECTF_WEAK_KEY   1
-#define SCM_WVECTF_WEAK_VALUE 2
-
-#define SCM_WVECT_WEAK_KEY_P(x) (SCM_I_WVECT_EXTRA(x) & SCM_WVECTF_WEAK_KEY)
-#define SCM_WVECT_WEAK_VALUE_P(x) (SCM_I_WVECT_EXTRA(x) & 
SCM_WVECTF_WEAK_VALUE)
-
-#define SCM_I_WVECT_TYPE(x)       (SCM_I_WVECT_EXTRA(x) & 7)
-#define SCM_I_SET_WVECT_TYPE(x,t) (SCM_I_SET_WVECT_EXTRA               \
-                                  ((x), (SCM_I_WVECT_EXTRA (x) & ~7) | (t)))
-#define SCM_IS_WHVEC(X)           (SCM_I_WVECT_TYPE (X) == 1)
-#define SCM_IS_WHVEC_V(X)         (SCM_I_WVECT_TYPE (X) == 2)
-#define SCM_IS_WHVEC_B(X)         (SCM_I_WVECT_TYPE (X) == 3)
-#define SCM_IS_WHVEC_ANY(X)       (SCM_I_WVECT_TYPE (X) != 0)
-
-
-/* Weak pairs.  */
-
-SCM_INTERNAL SCM scm_weak_car_pair (SCM car, SCM cdr);
-SCM_INTERNAL SCM scm_weak_cdr_pair (SCM car, SCM cdr);
-SCM_INTERNAL SCM scm_doubly_weak_pair (SCM car, SCM cdr);
-
-/* Testing the weak component(s) of a cell for reachability.  */
-#define SCM_WEAK_PAIR_WORD_DELETED_P(_cell, _word)             \
-  (SCM_UNPACK (SCM_CELL_OBJECT ((_cell), (_word))) == 0)
-#define SCM_WEAK_PAIR_CAR_DELETED_P(_cell)     \
-  (SCM_WEAK_PAIR_WORD_DELETED_P ((_cell), 0))
-#define SCM_WEAK_PAIR_CDR_DELETED_P(_cell)     \
-  (SCM_WEAK_PAIR_WORD_DELETED_P ((_cell), 1))
-
-#define SCM_WEAK_PAIR_DELETED_P(_cell)         \
-  ((SCM_WEAK_PAIR_CAR_DELETED_P (_cell))       \
-   || (SCM_WEAK_PAIR_CDR_DELETED_P (_cell)))
-
-/* Accessing the components of a weak cell.  These return `SCM_UNDEFINED' if
-   the car/cdr has been collected.  */
-#define SCM_WEAK_PAIR_WORD(_cell, _word)               \
-  (SCM_WEAK_PAIR_WORD_DELETED_P ((_cell), (_word))     \
-   ? SCM_UNDEFINED                                     \
-   : SCM_CELL_OBJECT ((_cell), (_word)))
-#define SCM_WEAK_PAIR_CAR(_cell)  (SCM_WEAK_PAIR_WORD ((_cell), 0))
-#define SCM_WEAK_PAIR_CDR(_cell)  (SCM_WEAK_PAIR_WORD ((_cell), 1))
-
-
-
-/* Weak vectors and weak hash tables.  */
-
-SCM_API SCM scm_make_weak_vector (SCM k, SCM fill);
-SCM_API SCM scm_weak_vector (SCM l);
-SCM_API SCM scm_weak_vector_p (SCM x);
-SCM_API SCM scm_make_weak_key_alist_vector (SCM k);
-SCM_API SCM scm_make_weak_value_alist_vector (SCM k);
-SCM_API SCM scm_make_doubly_weak_alist_vector (SCM k);
-SCM_API SCM scm_weak_key_alist_vector_p (SCM x);
-SCM_API SCM scm_weak_value_alist_vector_p (SCM x);
-SCM_API SCM scm_doubly_weak_alist_vector_p (SCM x);
-SCM_INTERNAL SCM scm_init_weaks_builtins (void);
-SCM_INTERNAL void scm_weaks_prehistory (void);
-SCM_INTERNAL void scm_init_weaks (void);
-
-SCM_INTERNAL void scm_i_init_weak_vectors_for_gc (void);
-SCM_INTERNAL void scm_i_mark_weak_vector (SCM w);
-SCM_INTERNAL int scm_i_mark_weak_vectors_non_weaks (void);
-SCM_INTERNAL void scm_i_remove_weaks_from_weak_vectors (void);
-
-
-#endif  /* SCM_WEAKS_H */
-
-/*
-  Local Variables:
-  c-file-style: "gnu"
-  End:
-*/
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 639a63c..b2e1271 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -886,15 +886,11 @@ VALUE."
 ;; properties within the object itself.
 
 (define (make-object-property)
-  (define-syntax-rule (with-mutex lock exp)
-    (dynamic-wind (lambda () (lock-mutex lock))
-                  (lambda () exp)
-                  (lambda () (unlock-mutex lock))))
-  (let ((prop (make-weak-key-hash-table))
-        (lock (make-mutex)))
+  ;; Weak tables are thread-safe.
+  (let ((prop (make-weak-key-hash-table)))
     (make-procedure-with-setter
-     (lambda (obj) (with-mutex lock (hashq-ref prop obj)))
-     (lambda (obj val) (with-mutex lock (hashq-set! prop obj val))))))
+     (lambda (obj) (hashq-ref prop obj))
+     (lambda (obj val) (hashq-set! prop obj val)))))
 
 
 
diff --git a/module/ice-9/weak-vector.scm b/module/ice-9/weak-vector.scm
index 09e2e0a..31d79ec 100644
--- a/module/ice-9/weak-vector.scm
+++ b/module/ice-9/weak-vector.scm
@@ -1,6 +1,6 @@
 ;;; installed-scm-file
 
-;;;; Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+;;;; Copyright (C) 2003, 2006, 2011 Free Software Foundation, Inc.
 ;;;; 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -19,13 +19,8 @@
 
 
 (define-module (ice-9 weak-vector)
-  :export (make-weak-vector list->weak-vector weak-vector weak-vector?
-          make-weak-key-alist-vector
-          make-weak-value-alist-vector
-          make-doubly-weak-alist-vector
-          weak-key-alist-vector?
-          weak-value-alist-vector?
-          doubly-weak-alist-vector?)  ; C
-  )
+  #:export (make-weak-vector list->weak-vector weak-vector weak-vector?))
 
-(%init-weaks-builtins) ; defined in libguile/weaks.c
+(eval-when (load eval compile)
+  (load-extension (string-append "libguile-" (effective-version))
+                  "scm_init_weak_vector_builtins"))
diff --git a/module/system/foreign.scm b/module/system/foreign.scm
index 37f9b41..e6e9655 100644
--- a/module/system/foreign.scm
+++ b/module/system/foreign.scm
@@ -192,10 +192,6 @@ which does the reverse.  PRINT must name a user-defined 
object printer."
                ;; PTR1 == PTR2 <-> (eq? (wrap PTR1) (wrap PTR2)).
                (let ((ptr->obj (make-weak-value-hash-table 3000)))
                  (lambda (ptr)
-                   ;; XXX: We can't use `hash-create-handle!' +
-                   ;; `set-cdr!' here because the former would create a
-                   ;; weak-cdr pair but the latter wouldn't register a
-                   ;; disappearing link (see `scm_hash_fn_set_x'.)
                    (or (hash-ref ptr->obj ptr)
                        (let ((o (%wrap ptr)))
                          (hash-set! ptr->obj ptr o)
diff --git a/test-suite/tests/weaks.test b/test-suite/tests/weaks.test
index d0f6c5e..9475eed 100644
--- a/test-suite/tests/weaks.test
+++ b/test-suite/tests/weaks.test
@@ -68,28 +68,28 @@
                     exception:wrong-type-arg
                     (list->weak-vector 32)))
 
- (with-test-prefix "make-weak-key-alist-vector"
+ (with-test-prefix "make-weak-key-hash-table"
                   (pass-if "create"
-                    (make-weak-key-alist-vector 17)
+                    (make-weak-key-hash-table 17)
                     #t)
                   (pass-if-exception "bad-args"
                     exception:wrong-type-arg
-                    (make-weak-key-alist-vector '(bad arg))))
- (with-test-prefix "make-weak-value-alist-vector"
+                    (make-weak-key-hash-table '(bad arg))))
+ (with-test-prefix "make-weak-value-hash-table"
                   (pass-if "create"
-                    (make-weak-value-alist-vector 17)
+                    (make-weak-value-hash-table 17)
                     #t)
                   (pass-if-exception "bad-args"
                     exception:wrong-type-arg
-                    (make-weak-value-alist-vector '(bad arg))))
+                    (make-weak-value-hash-table '(bad arg))))
 
- (with-test-prefix "make-doubly-weak-alist-vector"
+ (with-test-prefix "make-doubly-weak-hash-table"
                   (pass-if "create"
-                    (make-doubly-weak-alist-vector 17)
+                    (make-doubly-weak-hash-table 17)
                     #t)
                   (pass-if-exception "bad-args"
                     exception:wrong-type-arg
-                    (make-doubly-weak-alist-vector '(bad arg)))))
+                    (make-doubly-weak-hash-table '(bad arg)))))
 
 
 
@@ -138,9 +138,9 @@
   (or (not value)
       (equal? value initial-value)))
 
- (let ((x (make-weak-key-alist-vector 17))
-      (y (make-weak-value-alist-vector 17))
-      (z (make-doubly-weak-alist-vector 17))
+ (let ((x (make-weak-key-hash-table 17))
+      (y (make-weak-value-hash-table 17))
+      (z (make-doubly-weak-hash-table 17))
       (test-key "foo")
       (test-value "bar"))
   (with-test-prefix


hooks/post-receive
-- 
GNU Guile



reply via email to

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