~ chicken-core (chicken-5) abc3cf4dd97f77da2b6cc7c6c36937205ef2eea8
commit abc3cf4dd97f77da2b6cc7c6c36937205ef2eea8
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Fri Jun 30 15:28:08 2017 +0200
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Sun Jul 16 14:57:16 2017 +0200
Fix unpersistability sanity check for symbol GC
The sanity check we do just before dropping symbols from the symbol
table will ensure that the "bound value" slot of a symbol is either
empty or contains the symbol itself. If either is violated, the
assertion check fails.
This is correct, but keywords may have been moved by the GC and
replaced with forwarding pointers. This means the symbol value slot
could contain a forwarding pointer, which is definitely _not_ equal to
the symbol itself.
To fix this, before performing our sanity checks, we now fix up any
forwarding pointers in the symbol's value.
Signed-off-by: felix <felix@call-with-current-continuation.org>
diff --git a/runtime.c b/runtime.c
index 64020e24..311a1be7 100644
--- a/runtime.c
+++ b/runtime.c
@@ -4132,6 +4132,25 @@ C_regparm void C_fcall update_locative_table(int mode)
if(mode != GC_REALLOC) locative_table_count = hi;
}
+static C_regparm void fixup_symbol_forwards(C_word sym)
+{
+ C_word val, h;
+ int i, s = C_header_size(sym); /* 3 */
+
+ for (i = 0; i < s; i++) {
+ val = C_block_item(sym, i);
+ if (!C_immediatep(val)) {
+ h = C_block_header(val);
+
+ while(is_fptr(h)) {
+ val = fptr_to_ptr(h);
+ h = C_block_header(val);
+ }
+ C_set_block_item(sym, i, val);
+ }
+ }
+}
+
C_regparm void C_fcall update_symbol_tables(int mode)
{
int weakn = 0, i;
@@ -4159,17 +4178,11 @@ C_regparm void C_fcall update_symbol_tables(int mode)
#ifdef DEBUGBUILD
/* Detect inconsistencies before dropping / keeping the symbol */
+ fixup_symbol_forwards(sym);
{
C_word str = C_symbol_name(sym);
int str_perm;
- h = C_block_header(str);
-
- while(is_fptr(h)) {
- str = fptr_to_ptr(h);
- h = C_block_header(str);
- }
-
str_perm = !C_in_stackp(str) && !C_in_heapp(str) &&
!C_in_scratchspacep(str) &&
(mode == GC_REALLOC ? !C_in_new_heapp(str) : 1);
@@ -4196,7 +4209,10 @@ C_regparm void C_fcall update_symbol_tables(int mode)
if(last) C_set_block_item(last, 1, C_block_item(bucket,1));
else stp->table[ i ] = C_block_item(bucket,1);
+#ifndef NDEBUG
+ fixup_symbol_forwards(sym);
assert(!C_persistable_symbol(sym));
+#endif
++weakn;
} else {
C_set_block_item(bucket,0,sym); /* Might have moved */
Trap