aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2000-01-31 14:03:15 +0000
committerGerd Moellmann2000-01-31 14:03:15 +0000
commita0b581cce6fcde79946717a74630689ae5e5d815 (patch)
treeee8c25294154245358a666bbb7462301c700333d /src
parentc6035ee62dc938123178fb07a26a138791bde002 (diff)
downloademacs-a0b581cce6fcde79946717a74630689ae5e5d815.tar.gz
emacs-a0b581cce6fcde79946717a74630689ae5e5d815.zip
(sweep_weak_table): New function.
(sweep_weak_hash_tables): Use it. Keep on marking until there is no more change.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c163
1 files changed, 104 insertions, 59 deletions
diff --git a/src/fns.c b/src/fns.c
index 9621361653e..9ac0bbadf70 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -3440,6 +3440,7 @@ static unsigned sxhash_string P_ ((unsigned char *, int));
3440static unsigned sxhash_list P_ ((Lisp_Object, int)); 3440static unsigned sxhash_list P_ ((Lisp_Object, int));
3441static unsigned sxhash_vector P_ ((Lisp_Object, int)); 3441static unsigned sxhash_vector P_ ((Lisp_Object, int));
3442static unsigned sxhash_bool_vector P_ ((Lisp_Object)); 3442static unsigned sxhash_bool_vector P_ ((Lisp_Object));
3443static int sweep_weak_table P_ ((struct Lisp_Hash_Table *, int));
3443 3444
3444 3445
3445 3446
@@ -4022,6 +4023,86 @@ hash_clear (h)
4022 Weak Hash Tables 4023 Weak Hash Tables
4023 ************************************************************************/ 4024 ************************************************************************/
4024 4025
4026/* Sweep weak hash table H. REMOVE_ENTRIES_P non-zero means remove
4027 entries from the table that don't survive the current GC.
4028 REMOVE_ENTRIES_P zero means mark entries that are in use. Value is
4029 non-zero if anything was marked. */
4030
4031static int
4032sweep_weak_table (h, remove_entries_p)
4033 struct Lisp_Hash_Table *h;
4034 int remove_entries_p;
4035{
4036 int bucket, n, marked;
4037
4038 n = XVECTOR (h->index)->size & ~ARRAY_MARK_FLAG;
4039 marked = 0;
4040
4041 for (bucket = 0; bucket < n; ++bucket)
4042 {
4043 Lisp_Object idx, prev;
4044
4045 /* Follow collision chain, removing entries that
4046 don't survive this garbage collection. */
4047 idx = HASH_INDEX (h, bucket);
4048 prev = Qnil;
4049 while (!GC_NILP (idx))
4050 {
4051 int remove_p;
4052 int i = XFASTINT (idx);
4053 Lisp_Object next;
4054
4055 if (EQ (h->weak, Qkey))
4056 remove_p = !survives_gc_p (HASH_KEY (h, i));
4057 else if (EQ (h->weak, Qvalue))
4058 remove_p = !survives_gc_p (HASH_VALUE (h, i));
4059 else if (EQ (h->weak, Qt))
4060 remove_p = (!survives_gc_p (HASH_KEY (h, i))
4061 || !survives_gc_p (HASH_VALUE (h, i)));
4062 else
4063 abort ();
4064
4065 next = HASH_NEXT (h, i);
4066
4067 if (remove_entries_p)
4068 {
4069 if (remove_p)
4070 {
4071 /* Take out of collision chain. */
4072 if (GC_NILP (prev))
4073 HASH_INDEX (h, i) = next;
4074 else
4075 HASH_NEXT (h, XFASTINT (prev)) = next;
4076
4077 /* Add to free list. */
4078 HASH_NEXT (h, i) = h->next_free;
4079 h->next_free = idx;
4080
4081 /* Clear key, value, and hash. */
4082 HASH_KEY (h, i) = HASH_VALUE (h, i) = Qnil;
4083 HASH_HASH (h, i) = Qnil;
4084
4085 h->count = make_number (XFASTINT (h->count) - 1);
4086 }
4087 }
4088 else
4089 {
4090 if (!remove_p)
4091 {
4092 /* Make sure key and value survive. */
4093 mark_object (&HASH_KEY (h, i));
4094 mark_object (&HASH_VALUE (h, i));
4095 marked = 1;
4096 }
4097 }
4098
4099 idx = next;
4100 }
4101 }
4102
4103 return marked;
4104}
4105
4025/* Remove elements from weak hash tables that don't survive the 4106/* Remove elements from weak hash tables that don't survive the
4026 current garbage collection. Remove weak tables that don't survive 4107 current garbage collection. Remove weak tables that don't survive
4027 from Vweak_hash_tables. Called from gc_sweep. */ 4108 from Vweak_hash_tables. Called from gc_sweep. */
@@ -4030,8 +4111,29 @@ void
4030sweep_weak_hash_tables () 4111sweep_weak_hash_tables ()
4031{ 4112{
4032 Lisp_Object table; 4113 Lisp_Object table;
4033 struct Lisp_Hash_Table *h = 0, *prev; 4114 struct Lisp_Hash_Table *h, *prev;
4115 int marked;
4116
4117 /* Mark all keys and values that are in use. Keep on marking until
4118 there is no more change. This is necessary for cases like
4119 value-weak table A containing an entry X -> Y, where Y is used in a
4120 key-weak table B, Z -> Y. If B comes after A in the list of weak
4121 tables, X -> Y might be removed from A, although when looking at B
4122 one finds that it shouldn't. */
4123 do
4124 {
4125 marked = 0;
4126 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
4127 {
4128 h = XHASH_TABLE (table);
4129 if (h->size & ARRAY_MARK_FLAG)
4130 marked |= sweep_weak_table (h, 0);
4131 }
4132 }
4133 while (marked);
4034 4134
4135 /* Remove tables and entries that aren't used. */
4136 prev = NULL;
4035 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak) 4137 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
4036 { 4138 {
4037 prev = h; 4139 prev = h;
@@ -4040,64 +4142,7 @@ sweep_weak_hash_tables ()
4040 if (h->size & ARRAY_MARK_FLAG) 4142 if (h->size & ARRAY_MARK_FLAG)
4041 { 4143 {
4042 if (XFASTINT (h->count) > 0) 4144 if (XFASTINT (h->count) > 0)
4043 { 4145 sweep_weak_table (h, 1);
4044 int bucket, n;
4045
4046 n = XVECTOR (h->index)->size & ~ARRAY_MARK_FLAG;
4047 for (bucket = 0; bucket < n; ++bucket)
4048 {
4049 Lisp_Object idx, prev;
4050
4051 /* Follow collision chain, removing entries that
4052 don't survive this garbage collection. */
4053 idx = HASH_INDEX (h, bucket);
4054 prev = Qnil;
4055 while (!GC_NILP (idx))
4056 {
4057 int remove_p;
4058 int i = XFASTINT (idx);
4059 Lisp_Object next;
4060
4061 if (EQ (h->weak, Qkey))
4062 remove_p = !survives_gc_p (HASH_KEY (h, i));
4063 else if (EQ (h->weak, Qvalue))
4064 remove_p = !survives_gc_p (HASH_VALUE (h, i));
4065 else if (EQ (h->weak, Qt))
4066 remove_p = (!survives_gc_p (HASH_KEY (h, i))
4067 || !survives_gc_p (HASH_VALUE (h, i)));
4068 else
4069 abort ();
4070
4071 next = HASH_NEXT (h, i);
4072 if (remove_p)
4073 {
4074 /* Take out of collision chain. */
4075 if (GC_NILP (prev))
4076 HASH_INDEX (h, i) = next;
4077 else
4078 HASH_NEXT (h, XFASTINT (prev)) = next;
4079
4080 /* Add to free list. */
4081 HASH_NEXT (h, i) = h->next_free;
4082 h->next_free = idx;
4083
4084 /* Clear key, value, and hash. */
4085 HASH_KEY (h, i) = HASH_VALUE (h, i) = Qnil;
4086 HASH_HASH (h, i) = Qnil;
4087
4088 h->count = make_number (XFASTINT (h->count) - 1);
4089 }
4090 else
4091 {
4092 /* Make sure key and value survive. */
4093 mark_object (&HASH_KEY (h, i));
4094 mark_object (&HASH_VALUE (h, i));
4095 }
4096
4097 idx = next;
4098 }
4099 }
4100 }
4101 } 4146 }
4102 else 4147 else
4103 { 4148 {