Garbage collection 复制生成代码的垃圾收集

Garbage collection 复制生成代码的垃圾收集,garbage-collection,jit,Garbage Collection,Jit,复制(分代)垃圾收集提供了任何形式的自动内存管理的最佳性能,但需要修复指向重新定位的数据块的指针。在支持这种内存管理技术的语言中,这是通过禁止指针算法并确保所有指针都指向可识别对象的开头来实现的 如果您使用JIT编译器在运行时生成代码,事情看起来有点棘手,因为调用堆栈上的返回地址指向的不是代码块的开头,而是其中的随机位置,因此修复是一个问题 这通常是如何解决的?通常,您不会重新定位代码。这是因为修复堆栈和其他地址确实很复杂(想想代码片段之间的跳转),也因为这类代码实际上不需要垃圾收集(因为它只由

复制(分代)垃圾收集提供了任何形式的自动内存管理的最佳性能,但需要修复指向重新定位的数据块的指针。在支持这种内存管理技术的语言中,这是通过禁止指针算法并确保所有指针都指向可识别对象的开头来实现的

如果您使用JIT编译器在运行时生成代码,事情看起来有点棘手,因为调用堆栈上的返回地址指向的不是代码块的开头,而是其中的随机位置,因此修复是一个问题

这通常是如何解决的?

通常,您不会重新定位代码。这是因为修复堆栈和其他地址确实很复杂(想想代码片段之间的跳转),也因为这类代码实际上不需要垃圾收集(因为它只由您编写的代码操作,所以您可以进行手动内存管理)。您也不希望创建大量的机器代码(与应用程序对象相比),因此碎片化等问题并不重要

如果您坚持移动机器代码并修复堆栈,我认为有一种方法:与Mark Compact类似,构建一个“断表”(我不知道这个名称从何而来;“重新定位表”可能更清楚),它告诉您应该调整指针到移动对象的数量。现在,遍历返回地址的堆栈(当然是高度平台特定的),并在它们引用重新定位的代码时修复它们。搜索低于当前替换的返回地址的最高地址,而不是查找完全匹配的地址。您可以通过查看对象大小来检查此地址是否确实引用了某些移动的机器代码(毕竟,您有一个指向对象开头的指针)。由于各种原因,这种方法并不适用于所有对象


不过,做类似事情还有其他原因。某些JIT编译器具有堆栈替换功能,这意味着创建某些机器代码的新版本(例如,更优化或更少优化),并用它替换所有出现的旧版本。不过,这远比修复返回地址复杂得多。您必须确保新版本在逻辑上与旧版本保持一致。我不熟悉这是如何实现的,因此我不会详细介绍。

我想说,代码在传递给JIT之前已经过验证。