mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-08 22:32:26 +02:00
Fixed `scm_fixup_weak_alist ()'; update weak hash table size as needed.
* libguile/hashtab.c (scm_fixup_weak_alist): Added a REMOVED_ITEMS parameter. Fixed a bug in the case where PREV is `SCM_EOL'. (IS_WEAK_THING): New macro. (START_WEAK_BUCKET_FIXUP): New macro. (END_WEAK_BUCKET_FIXUP): New macro. (scm_hash_fn_get_handle)[buckets]: New variable. Use the above macros. (scm_hash_fn_create_handle_x): Likewise. (scm_hash_fn_remove_x): Likewise. git-archimport-id: lcourtes@laas.fr--2005-libre/guile-core--boehm-gc--1.9--patch-9
This commit is contained in:
parent
e4d21e6bc9
commit
d9c82e2051
1 changed files with 69 additions and 40 deletions
|
@ -184,13 +184,16 @@ scm_doubly_weak_cell (SCM car, SCM cdr)
|
||||||
|
|
||||||
|
|
||||||
/* Return a ``usable'' version of ALIST, an alist of weak pairs. By
|
/* Return a ``usable'' version of ALIST, an alist of weak pairs. By
|
||||||
``usable'', we mean that it contains only valid Scheme objects. */
|
``usable'', we mean that it contains only valid Scheme objects. On
|
||||||
|
return, REMOVE_ITEMS is set to the number of pairs that have been
|
||||||
|
deleted. */
|
||||||
static SCM
|
static SCM
|
||||||
scm_fixup_weak_alist (SCM alist)
|
scm_fixup_weak_alist (SCM alist, size_t *removed_items)
|
||||||
{
|
{
|
||||||
SCM result;
|
SCM result;
|
||||||
SCM prev = SCM_EOL;
|
SCM prev = SCM_EOL;
|
||||||
|
|
||||||
|
*removed_items = 0;
|
||||||
for (result = alist;
|
for (result = alist;
|
||||||
scm_is_pair (alist);
|
scm_is_pair (alist);
|
||||||
prev = alist, alist = SCM_CDR (alist))
|
prev = alist, alist = SCM_CDR (alist))
|
||||||
|
@ -205,10 +208,11 @@ scm_fixup_weak_alist (SCM alist)
|
||||||
/* Remove from ALIST weak pair PAIR whose car/cdr has been
|
/* Remove from ALIST weak pair PAIR whose car/cdr has been
|
||||||
nullified by the GC. */
|
nullified by the GC. */
|
||||||
if (prev == SCM_EOL)
|
if (prev == SCM_EOL)
|
||||||
result = alist;
|
result = SCM_CDR (alist);
|
||||||
else
|
else
|
||||||
SCM_SETCDR (prev, SCM_CDR (alist));
|
SCM_SETCDR (prev, SCM_CDR (alist));
|
||||||
|
|
||||||
|
(*removed_items)++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +221,44 @@ scm_fixup_weak_alist (SCM alist)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper macros. */
|
||||||
|
|
||||||
|
/* Return true if OBJ is either a weak hash table or a weak alist vector (as
|
||||||
|
defined in `weaks.[ch]').
|
||||||
|
FIXME: We should eventually keep only weah hash tables. */
|
||||||
|
/* XXX: We assume that if OBJ is a vector, then it's a _weak_ vector. */
|
||||||
|
#define IS_WEAK_THING(_obj) \
|
||||||
|
((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table))) \
|
||||||
|
|| (SCM_I_IS_VECTOR (table)))
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
vector. */
|
||||||
|
#define START_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
size_t _removed; \
|
||||||
|
\
|
||||||
|
/* Disable the GC so that ALIST remains valid until ASSOC_FN has \
|
||||||
|
returned. */ \
|
||||||
|
/* FIXME: We could maybe trigger a rehash here depending on whether \
|
||||||
|
`scm_fixup_weak_alist ()' noticed some change. */ \
|
||||||
|
GC_disable (); \
|
||||||
|
(_bucket) = scm_fixup_weak_alist ((_bucket), &_removed); \
|
||||||
|
SCM_SIMPLE_VECTOR_SET ((_buckets), (_idx), (_bucket)); \
|
||||||
|
\
|
||||||
|
if ((_removed) && (SCM_HASHTABLE_P (_obj))) \
|
||||||
|
SCM_SET_HASHTABLE_N_ITEMS ((_obj), \
|
||||||
|
SCM_HASHTABLE_N_ITEMS (_obj) - _removed); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
/* Terminate a weak bucket fixup phase. */
|
||||||
|
#define END_WEAK_BUCKET_FIXUP(_obj, _buckets, _idx, _bucket) \
|
||||||
|
do { GC_enable (); } while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
make_hash_table (int flags, unsigned long k, const char *func_name)
|
make_hash_table (int flags, unsigned long k, const char *func_name)
|
||||||
|
@ -554,36 +596,31 @@ scm_hash_fn_get_handle (SCM table, SCM obj, unsigned long (*hash_fn)(), SCM (*as
|
||||||
{
|
{
|
||||||
int weak = 0;
|
int weak = 0;
|
||||||
unsigned long k;
|
unsigned long k;
|
||||||
SCM alist, h;
|
SCM buckets, alist, h;
|
||||||
|
|
||||||
if (SCM_HASHTABLE_P (table))
|
if (SCM_HASHTABLE_P (table))
|
||||||
table = SCM_HASHTABLE_VECTOR (table);
|
buckets = SCM_HASHTABLE_VECTOR (table);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
SCM_VALIDATE_VECTOR (1, table);
|
SCM_VALIDATE_VECTOR (1, table);
|
||||||
if (SCM_SIMPLE_VECTOR_LENGTH (table) == 0)
|
buckets = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SCM_SIMPLE_VECTOR_LENGTH (buckets) == 0)
|
||||||
return SCM_BOOL_F;
|
return SCM_BOOL_F;
|
||||||
k = hash_fn (obj, SCM_SIMPLE_VECTOR_LENGTH (table), closure);
|
k = hash_fn (obj, SCM_SIMPLE_VECTOR_LENGTH (buckets), closure);
|
||||||
if (k >= SCM_SIMPLE_VECTOR_LENGTH (table))
|
if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
|
||||||
scm_out_of_range ("hash_fn_get_handle", scm_from_ulong (k));
|
scm_out_of_range ("hash_fn_get_handle", scm_from_ulong (k));
|
||||||
|
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (table, k);
|
weak = IS_WEAK_THING (table);
|
||||||
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
|
|
||||||
/* XXX: We assume that if TABLE is a vector, then it's a weak vector. */
|
if (weak)
|
||||||
if ((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table)))
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
|| (SCM_I_IS_VECTOR (table)))
|
|
||||||
{
|
|
||||||
/* Disable the GC so that ALIST remains valid until ASSOC_FN has
|
|
||||||
returned. */
|
|
||||||
/* FIXME: We could maybe trigger a rehash here depending on whether
|
|
||||||
`scm_fixup_weak_alist ()' noticed some change. */
|
|
||||||
GC_disable ();
|
|
||||||
weak = 1;
|
|
||||||
alist = scm_fixup_weak_alist (alist);
|
|
||||||
}
|
|
||||||
|
|
||||||
h = assoc_fn (obj, alist, closure);
|
h = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
GC_enable ();
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -614,18 +651,14 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_
|
||||||
if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
|
if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
|
||||||
scm_out_of_range ("hash_fn_create_handle_x", scm_from_ulong (k));
|
scm_out_of_range ("hash_fn_create_handle_x", scm_from_ulong (k));
|
||||||
|
|
||||||
|
weak = IS_WEAK_THING (table);
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
if ((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table)))
|
if (weak)
|
||||||
|| (SCM_I_IS_VECTOR (table)))
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
{
|
|
||||||
GC_disable ();
|
|
||||||
weak = 1;
|
|
||||||
alist = scm_fixup_weak_alist (alist);
|
|
||||||
}
|
|
||||||
|
|
||||||
it = assoc_fn (obj, alist, closure);
|
it = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
GC_enable ();
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
|
|
||||||
if (scm_is_true (it))
|
if (scm_is_true (it))
|
||||||
return it;
|
return it;
|
||||||
|
@ -735,18 +768,14 @@ scm_hash_fn_remove_x (SCM table, SCM obj,
|
||||||
if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
|
if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
|
||||||
scm_out_of_range ("hash_fn_remove_x", scm_from_ulong (k));
|
scm_out_of_range ("hash_fn_remove_x", scm_from_ulong (k));
|
||||||
|
|
||||||
|
weak = IS_WEAK_THING (table);
|
||||||
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||||
if ((SCM_HASHTABLE_P (table) && (SCM_HASHTABLE_WEAK_P (table)))
|
if (weak)
|
||||||
|| (SCM_I_IS_VECTOR (table)))
|
START_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
{
|
|
||||||
GC_disable ();
|
|
||||||
weak = 1;
|
|
||||||
alist = scm_fixup_weak_alist (alist);
|
|
||||||
}
|
|
||||||
|
|
||||||
h = assoc_fn (obj, alist, closure);
|
h = assoc_fn (obj, alist, closure);
|
||||||
if (weak)
|
if (weak)
|
||||||
GC_enable ();
|
END_WEAK_BUCKET_FIXUP (table, buckets, k, alist);
|
||||||
|
|
||||||
if (scm_is_true (h))
|
if (scm_is_true (h))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue