summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gc.c42
-rw-r--r--gc.h1
-rw-r--r--hash.c34
3 files changed, 67 insertions, 10 deletions
diff --git a/gc.c b/gc.c
index eafc354c..5fbf5c88 100644
--- a/gc.c
+++ b/gc.c
@@ -497,6 +497,43 @@ tail_call:
assert (0 && "corrupt type field");
}
+static void mark_obj_norec(val obj)
+{
+ type_t t;
+
+ if (!is_ptr(obj))
+ return;
+
+ t = obj->t.type;
+
+ if ((t & REACHABLE) != 0)
+ return;
+
+#if CONFIG_GEN_GC
+ if (!full_gc && obj->t.gen > 0)
+ return;
+#endif
+
+ if ((t & FREE) != 0)
+ abort();
+
+#if CONFIG_GEN_GC
+ if (obj->t.gen == -1)
+ obj->t.gen = 0; /* Will be promoted to generation 1 by sweep_one */
+#endif
+
+ obj->t.type = convert(type_t, t | REACHABLE);
+
+#if CONFIG_EXTRA_DEBUGGING
+ if (obj == break_obj) {
+#if HAVE_VALGRIND
+ VALGRIND_PRINTF_BACKTRACE("object %p marked\n", convert(void *, obj));
+#endif
+ breakpt();
+ }
+#endif
+}
+
void cobj_mark_op(val obj)
{
(void) obj;
@@ -959,6 +996,11 @@ void gc_mark(val obj)
mark_obj(obj);
}
+void gc_mark_norec(val obj)
+{
+ mark_obj_norec(obj);
+}
+
void gc_conservative_mark(val maybe_obj)
{
mark_obj_maybe(maybe_obj);
diff --git a/gc.h b/gc.h
index e89e695a..464268bf 100644
--- a/gc.h
+++ b/gc.h
@@ -36,6 +36,7 @@ void gc(void);
int gc_state(int);
int gc_inprogress(void);
void gc_mark(val);
+void gc_mark_norec(val obj);
void gc_conservative_mark(val);
void gc_mark_mem(val *low, val *high);
int gc_is_reachable(val);
diff --git a/hash.c b/hash.c
index f258bcb7..c5db4941 100644
--- a/hash.c
+++ b/hash.c
@@ -1357,11 +1357,15 @@ static void do_weak_tables(void)
for (; h != 0; h = h->next) {
ucnum i, c = 0;
+ val table = h->table;
+ val *vec = table->v.vec;
+ ucnum mask = h->mask;
+
/* The table of a weak hash was spuriously reached by conservative GC;
it's a waste of time doing weak processing, since all keys and
values have been transitively marked as reachable; and so we
won't find anything to remove. */
- if (gc_is_reachable(h->table))
+ if (gc_is_reachable(table))
continue;
switch (h->wkopt) {
@@ -1371,8 +1375,8 @@ static void do_weak_tables(void)
case hash_weak_keys:
/* Sweep through all entries. Delete any which have keys
that are garbage. */
- for (i = 0; i <= h->mask; i++) {
- val *pchain = &h->table->v.vec[i];
+ for (i = 0; i <= mask; i++) {
+ val *pchain = &vec[i];
val *iter;
for (iter = pchain; *iter; ) {
@@ -1384,6 +1388,8 @@ static void do_weak_tables(void)
breakpt();
#endif
} else {
+ gc_mark(entry);
+ gc_mark_norec(*iter);
iter = us_cdr_p(*iter);
c++;
}
@@ -1393,8 +1399,8 @@ static void do_weak_tables(void)
case hash_weak_vals:
/* Sweep through all entries. Delete any which have values
that are garbage. */
- for (i = 0; i <= h->mask; i++) {
- val *pchain = &h->table->v.vec[i];
+ for (i = 0; i <= mask; i++) {
+ val *pchain = &vec[i];
val *iter;
for (iter = pchain; *iter; ) {
@@ -1406,6 +1412,8 @@ static void do_weak_tables(void)
breakpt();
#endif
} else {
+ gc_mark(entry);
+ gc_mark_norec(*iter);
iter = us_cdr_p(*iter);
c++;
}
@@ -1415,8 +1423,8 @@ static void do_weak_tables(void)
case hash_weak_and:
/* Sweep through all entries. Delete any which have keys
and values that are garbage. */
- for (i = 0; i <= h->mask; i++) {
- val *pchain = &h->table->v.vec[i];
+ for (i = 0; i <= mask; i++) {
+ val *pchain = &vec[i];
val *iter;
for (iter = pchain; *iter; ) {
@@ -1430,6 +1438,8 @@ static void do_weak_tables(void)
breakpt();
#endif
} else {
+ gc_mark(entry);
+ gc_mark_norec(*iter);
iter = us_cdr_p(*iter);
c++;
}
@@ -1439,8 +1449,8 @@ static void do_weak_tables(void)
case hash_weak_or:
/* Sweep through all entries. Delete any which have keys
or values that are garbage. */
- for (i = 0; i <= h->mask; i++) {
- val *pchain = &h->table->v.vec[i];
+ for (i = 0; i <= mask; i++) {
+ val *pchain = &vec[i];
val *iter;
for (iter = pchain; *iter; ) {
@@ -1454,6 +1464,8 @@ static void do_weak_tables(void)
breakpt();
#endif
} else {
+ gc_mark(entry);
+ gc_mark_norec(*iter);
iter = us_cdr_p(*iter);
c++;
}
@@ -1463,7 +1475,9 @@ static void do_weak_tables(void)
}
/* Garbage is gone now. Seal things by marking the vector. */
- gc_mark(h->table);
+ gc_mark_norec(table);
+ gc_mark(vec[vec_alloc]);
+ gc_mark(vec[vec_length]);
h->count = c;
}