.net - .net core 源码中如何维护局部变量使用信息

标签 .net garbage-collection clr jit

This great answer解释了 GC 如何在方法完成执行之前收集局部变量:

The jitter performs two important duties when it compiles the IL for a method into machine code. ... It also generates a table that describes how the local variables inside the method body are used. That table has an entry for each method argument and local variable with two addresses. The address where the variable will first store an object reference. And the address of the machine code instruction where that variable is no longer used. ... The "no longer used" address in the table is very important. It makes the garbage collector very efficient. It can collect an object reference, even if it is used inside a method and that method hasn't finished executing yet.



我很好奇 JIT 创建的内部表的样子,以及如何在 中维护“不再使用”的地址。真正的clr源代码 .任何人都可以在最近开源的 coreclr source code 中向我展示相关的代码片段吗? ?

最佳答案

免责声明:我不是 CLR 或 RyuJIT 方面的专家。我可能完全错了。

我遇到了以下sectionRyuJIT chapterBook of the Runtime :

For lvlVars with tracked lifetimes, or for expression involving GC references, we report the range over which the reference is live. This is done by the emitter, which adds this information to the instruction group, and which terminates instruction groups when the GC info changes.



似乎存储此信息的结构可以在 jit/jitgcinfo.h 中找到。看起来像这样:
struct varPtrDsc
{
    varPtrDsc   *   vpdNext;

    unsigned        vpdVarNum;         // which variable is this about?

    unsigned        vpdBegOfs ;        // the offset where life starts
    unsigned        vpdEndOfs;         // the offset where life starts
};

我上面引用的段落表明这些字段由“发射器”填充,我相信它们的意思是 jit/emit.cpp .

生命周期间隔的开始设置在 emitter::emitGCvarLiveSet() ;相关摘录是(为简洁起见,删除了空格):
/* Allocate a lifetime record */
desc = new (emitComp, CMK_GC) varPtrDsc;
desc->vpdBegOfs = emitCurCodeOffs(addr);
#ifdef DEBUG
desc->vpdEndOfs = 0xFACEDEAD;
#endif
desc->vpdVarNum = offs;
desc->vpdNext = NULL;

生命周期的结束以类似的方式设置,在 emitter::emitGCvarDeadSet() 中。 :
/* Record the death code offset */
assert(desc->vpdEndOfs == 0xFACEDEAD);
       desc->vpdEndOfs  = emitCurCodeOffs(addr);

最后,这些表格似乎是写在 jit/gcencode.cpp 中的。 ,特别是在 GCInfo::gcMakeVarPtrTable() .

如果您想进一步探索,希望这将作为起点。

关于.net - .net core 源码中如何维护局部变量使用信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30416520/

相关文章:

c# - 创建一个包含单个字符串 N 次的 List<string>

c# - 经常调用的方法中的新临时变量

c# - 我们应该总是在类中包含一个默认构造函数吗?

.net - 在带有 .NET 2 (mscorwks) 和 .NET 4 (clr) 的转储中使用 SOS

c# - 在 .NET Core 2.0 中使用 COM 对象

.net - 在外部触发 .NET 垃圾回收

Hadoop DataNode 内存消耗和 GC 行为

c# - 对 CLR 施加内存限制

c# - 为什么要装箱引用类型?

c# - 一个关于 LINQ to XML 的简单问题