我是 LLVM 新手,我正在尝试实现一个使用 statepoint API 的垃圾收集器。我已经阅读了所有文档,并且我想我对我前面的道路有所了解。然而,我对这是正确的道路没有信心。
我还没能在网上找到使用状态点示例策略的运行时实现。 LLVM 文档在
/llvm/runtime/
下的存储库中提到了示例,但它们似乎已经消失了。
以下是我对需要做什么的理解:
我想使用 statepoint API 而不是
gc_root
,因为文档建议在新项目中使用它。我明白我需要执行以下操作:
使用
UseStatepoints = true
声明自定义GC策略;和 UseRS4GC = true
或使用 statepoint-example
内置策略。我计划使用 statepoint-example
除非我遇到阻止我使用它的技术问题。
注释我的所有函数以使用 setGC 来使用此策略:
#include <llvm/IR/IRBuilder.h>
// ...
Function *fn = Function::Create(prototype, Function::ExternalLinkage, function_name,
module.get());
fn.setGC("statepoint-example");
使用RewriteStatepointsForGC转换过程将自动引入注释,例如
@llvm.experimental.gc.statepoint
和@llvm.experimental.gc.relocate
。
使用
PlaceSafepoints
转换过程在安全点自动添加对 safepoint_poll
的调用。
我的 GC 应该有一个初始化阶段,该阶段在应用程序启动之前调用,并使用
GCFunctionMetadata::roots_begin()
中的 end()
和 GCMetadataPrinter
来访问堆栈映射。堆栈映射应采用以下格式:
Header {
uint8 : Stack Map Version (current version is 3)
uint8 : Reserved (expected to be 0)
uint16 : Reserved (expected to be 0)
}
uint32 : NumFunctions
uint32 : NumConstants
uint32 : NumRecords
StkSizeRecord[NumFunctions] {
uint64 : Function Address
uint64 : Stack Size (or UINT64_MAX if not statically known)
uint64 : Record Count
}
Constants[NumConstants] {
uint64 : LargeConstant
}
StkMapRecord[NumRecords] {
uint64 : PatchPoint ID
uint32 : Instruction Offset
uint16 : Reserved (record flags)
uint16 : NumLocations
Location[NumLocations] {
uint8 : Register | Direct | Indirect | Constant | ConstantIndex
uint8 : Reserved (expected to be 0)
uint16 : Location Size
uint16 : Dwarf RegNum
uint16 : Reserved (expected to be 0)
int32 : Offset or SmallConstant
}
uint32 : Padding (only if required to align to 8 byte)
uint16 : Padding
uint16 : NumLiveOuts
LiveOuts[NumLiveOuts]
uint16 : Dwarf RegNum
uint8 : Reserved
uint8 : Size in Bytes
}
uint32 : Padding (only if required to align to 8 byte)
然后,我可以将堆栈映射(可选)映射到易于 GC 使用的数据结构。
运行时应实现在安全点调用的函数
safepoint_poll
(步骤 4),并使用步骤 5 中收集的数据来检查是否需要垃圾收集过程。
有经验的人可以确认我是否走在正确的道路上吗?如果您知道我在哪里可以找到示例实现,那就太棒了。
谢谢!
要使用Statepoint API,您必须创建一个“自定义垃圾收集(GC)策略;启用状态点和其他选项
class MyGC : public llvm::GCStrategy {
public:
MyGC() {
UseStatepoints = true;
UseRS4GC = true;
}
};
使用这些转换过程添加状态点和安全点。在 LLVM,您可以通过
PassManager
: 应用这些转换
llvm::legacy::PassManager PM;
PM.add(llvm::createRewriteStatepointsForGC());
PM.add(llvm::createPlaceSafepoints());
PM.run(*module);
LLVM 的源代码通常是您可以找到 GC 策略和状态点的最佳示例的地方。
使用来源:
LLVM GC 文档:https://llvm.org/docs/Statepoints.html
LLVM 垃圾收集 (GC) 文档:https://llvm.org/docs/GarbageCollection.html
我的经验:http://localhost:3000/you_cannot_react ;)
我希望这个解决方案对您有所帮助,如果遇到其他问题,您可以告诉我