Skip to content

Commit 2696b9c

Browse files
committed
Fix siod's gc implementation when used with GLIBC.
Patch from LuoYuanke -- In the siod gc, it depends on setjmp(...) to get the value of callee saved register value, and traverse those register to get the possible local object pointer. Also it traverse current stack to get the possible local object pointer. For setjmp(...) on glibc X86-64, the rbp register (callee saved register) is NOT saved in the setjmp buffer, so object that pointed by rbp is NOT considered as local object variable and its memory is collected as garbage. This patch is to use getcontext(...) to get more register value of current context and traverse those register to protect object from garbage collection. This bug is not easy to expose, because usually rbp has been saved in stack when do garbage collection, so the object pointer can be scanned from stack. However when compiler do some optimization on register allocation or licm, the rbp live in gc_mark_and_sweep(...) and rbp is pointing to an object. In such situation, siod failed to run test.scm because object is collected as garbage unexpectedly. Differential Revision: D60039 llvm-svn: 357986
1 parent 13c70c6 commit 2696b9c

File tree

1 file changed

+13
-0
lines changed
  • MultiSource/Applications/siod

1 file changed

+13
-0
lines changed

MultiSource/Applications/siod/slib.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ long inums_dim = 256;
129129
struct user_type_hooks *user_types = NULL;
130130
long user_tc_next = tc_user_min;
131131
struct gc_protected *protected_registers = NULL;
132+
#if defined(__GLIBC__)
133+
ucontext_t save_regs_gc_mark;
134+
#else
132135
jmp_buf save_regs_gc_mark;
136+
#endif
133137
double gc_rt;
134138
long gc_cells_collected;
135139
char *user_ch_readm = "";
@@ -1266,9 +1270,18 @@ void gc_mark_and_sweep(void)
12661270
{heap->type = tc_free_cell;
12671271
heap->gc_mark = 0;
12681272
++heap;}
1273+
#if defined(__GLIBC__)
1274+
// With glibc, some register is mangled in jmp buffer, so object that
1275+
// is pointed by those register is collected as garbage. We use getcontext
1276+
// to avoid such issue.
1277+
getcontext(&save_regs_gc_mark);
1278+
mark_locations((LISP *) &save_regs_gc_mark.uc_mcontext,
1279+
(LISP *) (((char *) &save_regs_gc_mark.uc_mcontext) + sizeof(mcontext_t)));
1280+
#else
12691281
setjmp(save_regs_gc_mark);
12701282
mark_locations((LISP *) save_regs_gc_mark,
12711283
(LISP *) (((char *) save_regs_gc_mark) + sizeof(save_regs_gc_mark)));
1284+
#endif
12721285
mark_protected_registers();
12731286
mark_locations((LISP *) stack_start_ptr,
12741287
(LISP *) &stack_end);

0 commit comments

Comments
 (0)