[test-suite] r357986 - Fix siod's gc implementation when used with GLIBC.

James Y Knight via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 9 02:21:46 PDT 2019


Author: jyknight
Date: Tue Apr  9 02:21:45 2019
New Revision: 357986

URL: http://llvm.org/viewvc/llvm-project?rev=357986&view=rev
Log:
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

Modified:
    test-suite/trunk/MultiSource/Applications/siod/slib.c

Modified: test-suite/trunk/MultiSource/Applications/siod/slib.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Applications/siod/slib.c?rev=357986&r1=357985&r2=357986&view=diff
==============================================================================
--- test-suite/trunk/MultiSource/Applications/siod/slib.c (original)
+++ test-suite/trunk/MultiSource/Applications/siod/slib.c Tue Apr  9 02:21:45 2019
@@ -129,7 +129,11 @@ long inums_dim = 256;
 struct user_type_hooks *user_types = NULL;
 long user_tc_next = tc_user_min;
 struct gc_protected *protected_registers = NULL;
+#if defined(__GLIBC__)
+ucontext_t save_regs_gc_mark;
+#else
 jmp_buf save_regs_gc_mark;
+#endif
 double gc_rt;
 long gc_cells_collected;
 char *user_ch_readm = "";
@@ -1266,9 +1270,18 @@ void gc_mark_and_sweep(void)
    {heap->type = tc_free_cell;
     heap->gc_mark = 0;
     ++heap;}
+#if defined(__GLIBC__)
+ // With glibc, some register is mangled in jmp buffer, so object that
+ // is pointed by those register is collected as garbage. We use getcontext
+ // to avoid such issue.
+ getcontext(&save_regs_gc_mark);
+ mark_locations((LISP *) &save_regs_gc_mark.uc_mcontext,
+                (LISP *) (((char *) &save_regs_gc_mark.uc_mcontext) + sizeof(mcontext_t)));
+#else
  setjmp(save_regs_gc_mark);
  mark_locations((LISP *) save_regs_gc_mark,
 		(LISP *) (((char *) save_regs_gc_mark) + sizeof(save_regs_gc_mark)));
+#endif
  mark_protected_registers();
  mark_locations((LISP *) stack_start_ptr,
 		(LISP *) &stack_end);




More information about the llvm-commits mailing list