编译语言中的垃圾收集实现

时间:2011-08-17 23:35:20

标签: compiler-construction garbage-collection language-implementation

在实现精确的垃圾收集时,总是存在弄清堆栈中哪些字是指针以及哪些是其他类型的数据(如整数或浮点数)的问题。解释语言通常通过使所有东西成为指针来解决这个问题;某些语言(如Lisp)的编译器通常使用标记位来区分指针和整数来解决它。

但是,Java和C#等语言的JIT编译器如何支持完整的无盒装机器字整数和浮点数?他们如何判断堆栈和CPU寄存器的哪些内容是指针?

2 个答案:

答案 0 :(得分:10)

此类语言的字节码始终包含完整类型信息。它存储在元数据中(例如,用于参数类型)或隐含在操作码中(例如,可能存在用于添加整数或浮点数的不同操作码)。

优化代码时,编译器可以访问此信息并使用它来改进优化。它还使用该信息为特定 GC安全点的已编译代码生成元数据。

GC安全点是代码中的一个位置,可以安全地中断线程以安排另一个线程或执行垃圾回收。在GC安全点,我们有必要的元数据可以找出哪些寄存器包含指针而哪些寄存器不包含指针。例如,在Hotspot JVM中,循环始终包含来自内存中特殊位置的读取。该读取的结果未使用,但如果指令读取的地址被读保护,则发生页面错误。这可以通过简单地将该页面设置为只读来用于在任意时间点中断线程。一旦线程被中断,我们就会查看程序计数器,然后在哈希表中查找元数据。

其他需要GC安全点的地方是分配站点:分配可能会失败并导致GC发生。您可以通过一次为多个对象分配内存来减少安全点数。

编辑:请注意,使用GC安全点只是众多选项中的一种。正如SK逻辑所提到的,另一个选择是为指针和非指针使用单独的堆栈。很明显,在GC期间需要遍历一个堆栈的所有元素,但其他元素都不需要遍历。不过,你仍然需要注意寄存器中的指针。例如,只要寄存器中有实时指针,堆栈上也必须存在相同的指针。

第三个选项是使用影子堆栈,其中包含指向生成在真实堆栈上的根的指针的链接列表。有关详细信息,请参阅论文"Accurate Garbage Collection in an Uncooperative Environment" by Fergus Henderson (PDF)

答案 1 :(得分:0)

Java和C#等语言的指定方式是它们不需要要求精确收集。实现可能使用保守收集器,其中看起来像指针的位模式被视为指针(但实际上可能是整数或浮点数)。例如,Boehm collector是一个保守的收集器,可用于JIT编辑的语言。