C Boehm-Weiser垃圾收集器的机理

C Boehm-Weiser垃圾收集器的机理,c,assembly,garbage-collection,C,Assembly,Garbage Collection,我在读《不合作环境中的垃圾收集器》一文,想知道实现它有多难。本文描述了从处理器(除了堆栈)收集所有地址的需要。堆栈部分似乎很直观。除了在汇编中显式枚举每个寄存器外,还有其他方法从寄存器收集地址吗?让我们假设x86_64在类似POSIX的系统(如linux或mac)上运行 SetJmp实际上,由于Boehm和Weiser,那么一个基本的信息源就是该实现的源代码(它是开源的) 要收集寄存器值,您可能需要破坏setjmp()函数,该函数将寄存器的副本保存在自定义结构中(至少是那些应该在函数调用中保留的

我在读《不合作环境中的垃圾收集器》一文,想知道实现它有多难。本文描述了从处理器(除了堆栈)收集所有地址的需要。堆栈部分似乎很直观。除了在汇编中显式枚举每个寄存器外,还有其他方法从寄存器收集地址吗?让我们假设x86_64在类似POSIX的系统(如linux或mac)上运行


SetJmp

实际上,由于Boehm和Weiser,那么一个基本的信息源就是该实现的源代码(它是开源的)

要收集寄存器值,您可能需要破坏
setjmp()
函数,该函数将寄存器的副本保存在自定义结构中(至少是那些应该在函数调用中保留的寄存器)。但是这种结构没有标准化(它的内容名义上是不透明的),而且C编译器可能会专门处理
setjmp()
,这使得它对于除
longjmp()
之外的任何东西都有点微妙(这已经很难了)。一段内联装配似乎更容易、更安全

GC实现中的第一个硬部分似乎能够可靠地检测堆栈的开始和结束(注意复数形式:可能有线程,每个线程都有自己的堆栈)。这需要深入研究操作系统ABI的详细信息。当我的桌面系统是运行FreeBSD的Alpha机器时,Boehm Weiser实现无法在其上运行(尽管它在同一处理器上支持Linux)


第二个困难的部分将是当试图通过玩页面访问权限来实现代际、捕获写访问时。这同样需要阅读一些存在问题的文档和一些内联汇编。

我认为在x86_86上,他们使用flushrs汇编指令将寄存器放在堆栈上。如果这是错误的,我相信堆栈溢出方面的人会纠正我。

实现一个简单的收集器并不难:毕竟它只是一个算法。硬的部分如前所述,但我将添加最糟糕的部分:跟踪异常非常糟糕,停止线程更糟糕:在某些平台上根本无法做到这一点。还有一个问题是捕获所有移交给操作系统并暂时从程序中丢失的指针(在Windows窗口消息处理程序中经常发生)

我自己的多线程GC类似于BEHM收集器,或多或少标准C++,只有很少的黑客(使用JMPBUF或多或少肯定会工作)和稍微不那么恶劣的环境(没有例外)。但是它通过合作来阻止世界,这是非常糟糕的:如果你有一个繁忙的CPU,空闲的CPU会等待它。Boehm使用信号或其他操作系统功能试图停止线程,但支持非常脆弱


还要注意的是,英特尔i64处理器每个线程有两个堆栈。。一般来说,要解释这类事情有点困难。

当然,一旦你找到了堆栈框架,你就有足够的实现细节来了解寄存器。我不确定你是否正确,Hans。也许我们可以依靠C运行时环境的结构来解决这个问题。如果我们调用一个非内联malloc包装器,将寄存器刷新到堆栈(flushrs),也许我们可以使用任何局部变量的地址(本地到malloc),并在内存中移动到更高的位置,直到到达argv[0]的地址。