mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Implemented rehashing of weak hash tables.
* libguile/hashtab.c (weak_hashtables): Removed. (SCM_WEAK_CELL_DELETED_P): New macro. (START_WEAK_BUCKET_FIXUP): Added the HASHFN argument. Invoke `scm_i_rehash ()' when pairs have been removed. (END_WEAK_BUCKET_FIXUP): Added the HASHFN argument. (make_hash_table): Use `SCM_NEWSMOB2 ()' instead of `SCM_NEWSMOB3 ()' -- last argument used to be WEAK_HASHTABLES. (scm_i_rehash): Handle weak hash tables. (to_rehash): Removed. (scm_internal_hash_fold): Use `SCM_WEAK_CELL_DELETED_P ()' rather than hand-written equivalent code. (rehash_after_gc): Removed. (scm_hashtab_prehistory): Don't add it as an after-gc hook. * libguile/hashtab.h (SCM_HASHTABLE_NEXT): Removed. (SCM_HASHTABLE_NEXTLOC): Removed. (SCM_SET_HASHTABLE_NEXT): Removed. git-archimport-id: lcourtes@laas.fr--2005-libre/guile-core--boehm-gc--1.9--patch-38
This commit is contained in:
parent
651a073522
commit
c6a35e35f7
2 changed files with 44 additions and 79 deletions
|
@ -83,8 +83,6 @@ static unsigned long hashtable_size[] = {
|
||||||
|
|
||||||
static char *s_hashtable = "hashtable";
|
static char *s_hashtable = "hashtable";
|
||||||
|
|
||||||
SCM weak_hashtables = SCM_EOL;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Weak cells for use in weak alist vectors (aka. weak hash tables).
|
/* Weak cells for use in weak alist vectors (aka. weak hash tables).
|
||||||
|
@ -175,6 +173,10 @@ scm_doubly_weak_cell (SCM car, SCM cdr)
|
||||||
#define SCM_WEAK_CELL_CDR_DELETED_P(_cell) \
|
#define SCM_WEAK_CELL_CDR_DELETED_P(_cell) \
|
||||||
(SCM_WEAK_CELL_WORD_DELETED_P ((_cell), 1))
|
(SCM_WEAK_CELL_WORD_DELETED_P ((_cell), 1))
|
||||||
|
|
||||||
|
#define SCM_WEAK_CELL_DELETED_P(_cell) \
|
||||||
|
((SCM_WEAK_CELL_CAR_DELETED_P (_cell)) \
|
||||||
|
|| (SCM_WEAK_CELL_CDR_DELETED_P (_cell)))
|
||||||
|
|
||||||
/* Accessing the components of a weak cell. */
|
/* Accessing the components of a weak cell. */
|
||||||
#define SCM_WEAK_CELL_WORD(_cell, _word) \
|
#define SCM_WEAK_CELL_WORD(_cell, _word) \
|
||||||
((SCM_WEAK_CELL_WORD_DELETED_P ((_cell), (_word))) \
|
((SCM_WEAK_CELL_WORD_DELETED_P ((_cell), (_word))) \
|
||||||
|
@ -233,30 +235,36 @@ scm_fixup_weak_alist (SCM alist, size_t *removed_items)
|
||||||
((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table))) \
|
((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table))) \
|
||||||
|| (SCM_I_IS_VECTOR (table)))
|
|| (SCM_I_IS_VECTOR (table)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Fixup BUCKET, an alist part of weak hash table OBJ. BUCKETS is the full
|
/* Fixup BUCKET, an alist part of weak hash table OBJ. BUCKETS is the full
|
||||||
bucket vector for OBJ and IDX is the index of BUCKET within this
|
bucket vector for OBJ and IDX is the index of BUCKET within this
|
||||||
vector. See also `scm_internal_hash_fold ()'. */
|
vector. See also `scm_internal_hash_fold ()'. */
|
||||||
#define START_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket) \
|
#define START_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket, _hashfn) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
size_t _removed; \
|
size_t _removed; \
|
||||||
\
|
\
|
||||||
/* Disable the GC so that BUCKET remains valid until ASSOC_FN has \
|
/* Disable the GC so that BUCKET remains valid until ASSOC_FN has \
|
||||||
returned. */ \
|
returned. */ \
|
||||||
/* FIXME: We could maybe trigger a rehash here depending on whether \
|
/* FIXME: We could maybe trigger a rehash here depending on whether \
|
||||||
`scm_fixup_weak_alist ()' noticed some change. */ \
|
`scm_fixup_weak_alist ()' noticed some change. */ \
|
||||||
GC_disable (); \
|
GC_disable (); \
|
||||||
(_bucket) = scm_fixup_weak_alist ((_bucket), &_removed); \
|
(_bucket) = scm_fixup_weak_alist ((_bucket), &_removed); \
|
||||||
SCM_SIMPLE_VECTOR_SET ((_buckets), (_idx), (_bucket)); \
|
SCM_SIMPLE_VECTOR_SET ((_buckets), (_idx), (_bucket)); \
|
||||||
\
|
\
|
||||||
if ((_removed) && (SCM_HASHTABLE_P (_obj))) \
|
if ((_removed) && (SCM_HASHTABLE_P (_obj))) \
|
||||||
SCM_SET_HASHTABLE_N_ITEMS ((_obj), \
|
{ \
|
||||||
SCM_HASHTABLE_N_ITEMS (_obj) - _removed); \
|
SCM_SET_HASHTABLE_N_ITEMS ((_obj), \
|
||||||
} \
|
SCM_HASHTABLE_N_ITEMS (_obj) - _removed); \
|
||||||
|
scm_i_rehash ((_obj), (_hashfn), \
|
||||||
|
NULL, "START_WEAK_BUCKET_FIXUP"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
/* Terminate a weak bucket fixup phase. */
|
/* Terminate a weak bucket fixup phase. */
|
||||||
#define END_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket) \
|
#define END_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket, _hashfn) \
|
||||||
do { GC_enable (); } while (0)
|
do { GC_enable (); } while (0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,14 +291,9 @@ make_hash_table (int flags, unsigned long k, const char *func_name)
|
||||||
t->upper = 9 * n / 10;
|
t->upper = 9 * n / 10;
|
||||||
t->flags = flags;
|
t->flags = flags;
|
||||||
t->hash_fn = NULL;
|
t->hash_fn = NULL;
|
||||||
if (flags)
|
|
||||||
{
|
SCM_NEWSMOB2 (table, scm_tc16_hashtable, vector, t);
|
||||||
/* FIXME: We should eventually remove WEAK_HASHTABLES. */
|
|
||||||
SCM_NEWSMOB3 (table, scm_tc16_hashtable, vector, t, weak_hashtables);
|
|
||||||
weak_hashtables = table;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SCM_NEWSMOB3 (table, scm_tc16_hashtable, vector, t, SCM_EOL);
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,12 +308,6 @@ scm_i_rehash (SCM table,
|
||||||
unsigned long old_size;
|
unsigned long old_size;
|
||||||
unsigned long new_size;
|
unsigned long new_size;
|
||||||
|
|
||||||
if (SCM_HASHTABLE_P (table) && SCM_HASHTABLE_WEAK_P (table))
|
|
||||||
/* FIXME: We don't currently support weak hash table rehashing. In order
|
|
||||||
to support it, we need to pay attention to NULL pairs, as in
|
|
||||||
`scm_internal_hash_fold ()', `START_WEAK_BUCKET_FIXUP ()', et al. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table))
|
if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table))
|
||||||
{
|
{
|
||||||
/* rehashing is not triggered when i <= min_size */
|
/* rehashing is not triggered when i <= min_size */
|
||||||
|
@ -367,9 +364,15 @@ scm_i_rehash (SCM table,
|
||||||
while (scm_is_pair (ls))
|
while (scm_is_pair (ls))
|
||||||
{
|
{
|
||||||
unsigned long h;
|
unsigned long h;
|
||||||
|
|
||||||
cell = ls;
|
cell = ls;
|
||||||
handle = SCM_CAR (cell);
|
handle = SCM_CAR (cell);
|
||||||
ls = SCM_CDR (ls);
|
ls = SCM_CDR (ls);
|
||||||
|
|
||||||
|
if (SCM_WEAK_CELL_DELETED_P (handle))
|
||||||
|
/* HANDLE is a nullified weak pair: skip it. */
|
||||||
|
continue;
|
||||||
|
|
||||||
h = hash_fn (SCM_CAR (handle), new_size, closure);
|
h = hash_fn (SCM_CAR (handle), new_size, closure);
|
||||||
if (h >= new_size)
|
if (h >= new_size)
|
||||||
scm_out_of_range (func_name, scm_from_ulong (h));
|
scm_out_of_range (func_name, scm_from_ulong (h));
|
||||||
|
@ -400,39 +403,6 @@ hashtable_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* keep track of hash tables that need to shrink after scan */
|
|
||||||
static SCM to_rehash = SCM_EOL;
|
|
||||||
|
|
||||||
|
|
||||||
static void *
|
|
||||||
rehash_after_gc (void *dummy1 SCM_UNUSED,
|
|
||||||
void *dummy2 SCM_UNUSED,
|
|
||||||
void *dummy3 SCM_UNUSED)
|
|
||||||
{
|
|
||||||
if (!scm_is_null (to_rehash))
|
|
||||||
{
|
|
||||||
SCM first = to_rehash, last, h;
|
|
||||||
/* important to clear to_rehash here so that we don't get stuck
|
|
||||||
in an infinite loop if scm_i_rehash causes GC */
|
|
||||||
to_rehash = SCM_EOL;
|
|
||||||
h = first;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Rehash only when we have a hash_fn.
|
|
||||||
*/
|
|
||||||
if (SCM_HASHTABLE (h)->hash_fn)
|
|
||||||
scm_i_rehash (h, SCM_HASHTABLE (h)->hash_fn, NULL,
|
|
||||||
"rehash_after_gc");
|
|
||||||
last = h;
|
|
||||||
h = SCM_HASHTABLE_NEXT (h);
|
|
||||||
} while (!scm_is_null (h));
|
|
||||||
/* move tables back to weak_hashtables */
|
|
||||||
SCM_SET_HASHTABLE_NEXT (last, weak_hashtables);
|
|
||||||
weak_hashtables = first;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_c_make_hash_table (unsigned long k)
|
scm_c_make_hash_table (unsigned long k)
|
||||||
|
@ -578,11 +548,11 @@ scm_hash_fn_get_handle (SCM table, SCM obj, unsigned long (*hash_fn)(), SCM (*as
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
|
|
||||||
if (weak)
|
if (weak)
|
||||||
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
h = assoc_fn (obj, alist, closure);
|
h = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -616,11 +586,11 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_
|
||||||
weak = IS_WEAK_THING (table);
|
weak = IS_WEAK_THING (table);
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
if (weak)
|
if (weak)
|
||||||
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
it = assoc_fn (obj, alist, closure);
|
it = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
if (scm_is_true (it))
|
if (scm_is_true (it))
|
||||||
return it;
|
return it;
|
||||||
|
@ -733,11 +703,11 @@ scm_hash_fn_remove_x (SCM table, SCM obj,
|
||||||
weak = IS_WEAK_THING (table);
|
weak = IS_WEAK_THING (table);
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
if (weak)
|
if (weak)
|
||||||
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
h = assoc_fn (obj, alist, closure);
|
h = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
|
||||||
|
|
||||||
if (scm_is_true (h))
|
if (scm_is_true (h))
|
||||||
{
|
{
|
||||||
|
@ -1136,8 +1106,7 @@ scm_internal_hash_fold (SCM (*fn) (), void *closure, SCM init, SCM table)
|
||||||
|
|
||||||
if (IS_WEAK_THING (table))
|
if (IS_WEAK_THING (table))
|
||||||
{
|
{
|
||||||
if ((SCM_CAR (handle) == SCM_PACK (NULL))
|
if (SCM_WEAK_CELL_DELETED_P (handle))
|
||||||
|| (SCM_CDR (handle) == SCM_PACK (NULL)))
|
|
||||||
{
|
{
|
||||||
/* We hit a weak pair whose car/cdr has become
|
/* We hit a weak pair whose car/cdr has become
|
||||||
unreachable: unlink it from the bucket. */
|
unreachable: unlink it from the bucket. */
|
||||||
|
@ -1315,7 +1284,6 @@ scm_hashtab_prehistory ()
|
||||||
/* Initialize the hashtab SMOB type. */
|
/* Initialize the hashtab SMOB type. */
|
||||||
scm_tc16_hashtable = scm_make_smob_type (s_hashtable, 0);
|
scm_tc16_hashtable = scm_make_smob_type (s_hashtable, 0);
|
||||||
scm_set_smob_print (scm_tc16_hashtable, hashtable_print);
|
scm_set_smob_print (scm_tc16_hashtable, hashtable_print);
|
||||||
scm_c_hook_add (&scm_after_gc_c_hook, rehash_after_gc, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -39,9 +39,6 @@ SCM_API scm_t_bits scm_tc16_hashtable;
|
||||||
#define SCM_HASHTABLE_VECTOR(h) SCM_SMOB_OBJECT (h)
|
#define SCM_HASHTABLE_VECTOR(h) SCM_SMOB_OBJECT (h)
|
||||||
#define SCM_SET_HASHTABLE_VECTOR(x, v) SCM_SET_SMOB_OBJECT ((x), (v))
|
#define SCM_SET_HASHTABLE_VECTOR(x, v) SCM_SET_SMOB_OBJECT ((x), (v))
|
||||||
#define SCM_HASHTABLE(x) ((scm_t_hashtable *) SCM_SMOB_DATA_2 (x))
|
#define SCM_HASHTABLE(x) ((scm_t_hashtable *) SCM_SMOB_DATA_2 (x))
|
||||||
#define SCM_HASHTABLE_NEXT(x) SCM_SMOB_OBJECT_3 (x)
|
|
||||||
#define SCM_HASHTABLE_NEXTLOC(x) SCM_SMOB_OBJECT_3_LOC (x)
|
|
||||||
#define SCM_SET_HASHTABLE_NEXT(x, n) SCM_SET_SMOB_OBJECT_3 ((x), (n))
|
|
||||||
#define SCM_HASHTABLE_FLAGS(x) (SCM_HASHTABLE (x)->flags)
|
#define SCM_HASHTABLE_FLAGS(x) (SCM_HASHTABLE (x)->flags)
|
||||||
#define SCM_HASHTABLE_WEAK_KEY_P(x) \
|
#define SCM_HASHTABLE_WEAK_KEY_P(x) \
|
||||||
(SCM_HASHTABLE_FLAGS (x) & SCM_HASHTABLEF_WEAK_CAR)
|
(SCM_HASHTABLE_FLAGS (x) & SCM_HASHTABLEF_WEAK_CAR)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue