2010-09-11 38 views
1

我在阅读“不合作环境中的垃圾收集器”一文,并想知道实施它会有多困难。该论文描述了从处理器收集所有地址的需求(除堆栈外)。堆栈部分看起来很直观。除了在汇编中明确列举每个寄存器之外,是否有任何方法可以从寄存器中收集地址?假设x86_64位于类似POSIX的系统上,例如linux或mac。Boehm Weiser垃圾收集器的机制

的setjmp

+1

那么,当然,一旦你可以找到堆栈帧,你已经承诺足够的实现细节来了解寄存器。 – 2010-09-11 21:32:36

+0

我不确定你是对的,汉斯。也许我们可以依靠C运行时环境的结构来解决这个问题。如果我们调用一个将寄存器刷新到堆栈(flushrs)的非内联malloc包装器,也许我们可以使用任何局部变量的地址(malloc的本地变量)并在内存中移动更高的地址,直到达到argv [0]的地址。 – SetJmp 2010-09-29 13:39:26

回答

2

由于Boehm和韦瑟实际上implemented their GC,则信息的基本来源是实现(它是开源)的源代码。

要收集寄存器值,您可能需要破坏setjmp()函数,该函数会将寄存器的副本保存在自定义结构中(至少应该在函数调用中保留的那些寄存器)。但是这种结构不是标准化的(其内容名义上是不透明的),并且setjmp()可能由C编译器特别处理,使其用于除longjmp()之外的任何其他东西(这已经非常困难)。一行内联组装似乎更容易和更安全。

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

第二个艰难的部分将是试图进入世代,通过播放页面访问权限来阻止写入访问。这又需要阅读一些可疑存在的文档,以及一些内联汇编。

0

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

0

实现一个朴素的收集器并不难:它毕竟只是一个算法。难点在于说明,但我会加上最糟糕的:跟踪异常是令人讨厌的,并且停止线程更糟糕:在某些平台上根本无法完成。还有一个问题,即捕获所有交给操作系统的指针并暂时丢失(在Windows窗口消息处理程序中发生的很多事情)。

我自己的多线程GC与Boehm收集器类似,并且几乎没有标准C++(使用jmpbuf或多或少可以工作)以及稍微不太恶劣的环境(没有例外)。但它通过合作阻止了世界,这非常糟糕:如果你有一个繁忙的CPU,空闲的等待它。 Boehm使用信号或其他操作系统功能尝试停止线程,但支持非常脆弱。

另外请注意,英特尔i64处理器每个线程有两个堆栈..有点难以说明这种东西一般。