【问题标题】:"this" pointer in the clr abi documentclr abi 文档中的“this”指针
【发布时间】:2016-12-28 13:21:11
【问题描述】:
The "this" pointer
仅限 AMD64:在 .NET Framework 4.5 之前,托管的“this”指针是
就像原生的“this”指针一样对待(意味着它是第二个
调用使用返回 buffer 并在 RDX 中传递时的参数
而不是 RCX)。
我在clr abi文档中找到了上面的语句,根据我的理解是.NET Framework 4.5,“this”指针是调用使用返回时的第二个参数缓冲区并在RDX中通过;
所以我有两个问题:
缓冲区的含义是什么?缓冲区指的是流缓冲区,如 httpwebresponse 或其他什么?
如果我们使用静态类怎么样,我认为在那种情况下,不存在“this”指针并且上面的语句指定给实例对象,对吧?
【问题讨论】:
-
返回缓冲区在 MSDN 文档中关于 x64 调用约定的 Return Values 中进行了描述:否则,调用者将承担分配内存并将返回值的指针作为第一个传递的责任论据。
标签:
c#
.net
clr
windbg
coreclr
【解决方案1】:
很明显,微软一直在修补他们的 x64 abi。他们究竟做了什么,什么时候做的却非常不清楚,文档不完整,分散且过时。我个人认为 Agner Fog 所做的reverse-engineering work 是唯一真正可靠的信息来源。然而,他并没有解决托管代码生成问题。
声称在 4.5 中对此进行了更改是相当不可信的。更有可能的是,这在 RyuJIT 中发生了变化,新的 x64 抖动取代了相当有缺陷且无法维护的旧版 x64 抖动。最初在预览版中发布为 4.5.3,也许解释了 4.5 的声明,但后来增加到 4.6。这种变化的一个可能灵感来自 .NETCore 项目,Microsoft x64 abi 与 Unix 代码生成器(GNU 和 LLVM)的区别相当痛苦。
但与 C++ 编译器代码生成器更改不同(根据 Agner Fog, gack 在 VS2015 更新中进行了修改),此更改不太可能被破坏。不匹配只能在 pinvoke 中发生,抖动从不支持 CallingConvention.ThisCall。幸运的是,您的问题很容易回答:
缓冲区的含义是什么?
这只对返回“聚合类型”的方法很重要。换句话说,一个不再适合 CPU 寄存器的值。在 C# 中,这是一个 struct,进一步规定它必须是非平凡的(超过 2 个成员或非平凡的字段类型)。
方法调用者必须在其堆栈帧中为返回值(“缓冲区”)分配空间,并传递一个指向该空间的指针。该指针作为隐藏的额外参数传递给该方法。传统上是第一个参数,在隐藏的 this 参数之前。这使得this 成为第二个参数,因此通过 RDX 寄存器而不是 RCX 寄存器传递。更改顺序颠倒,this 始终是第一个参数并通过 RCX 传递,返回值指针是第二个。被调用的方法在返回之前将返回值复制到该缓冲区中。
如果我们使用静态类呢
仅与静态方法相关。然后没有额外的隐藏 this 参数,所以它被简单地省略了。实际上与之前的做法没有任何变化,隐藏的返回值指针自动始终是第一个参数,因此通过 RCX 传递。
如果这对您很重要,请务必利用调试器的“调试”>“窗口”>“反汇编”窗口。在一个小的测试程序上运行它,它很容易告诉你使用了哪些寄存器。