如何在 CIL 中的堆栈上处理不同的类型

Posted

技术标签:

【中文标题】如何在 CIL 中的堆栈上处理不同的类型【英文标题】:How are different types handled on the stack in CIL 【发布时间】:2014-07-22 14:47:28 【问题描述】:

使用 ildasm 进行实验以深入研究 CIL 代码,很明显 CIL 本身正在基于堆栈工作以支持像这样的表达式

IL_0001:    ldc.i4.s 13     ; 1f 0d
IL_0003:    stloc.0         ; 0a
IL_0004:    ldc.i4.s 31     ; 1f 1f
IL_0006:    stloc.1         ; 0b
IL_0007:    ldloc.0         ; 06
IL_0008:    ldloc.1         ; 07
IL_0009:    add             ; 58

使用ldc.r4 <num>float32 执行相同操作而不是int32特定元素在堆栈上的类型的元数据。是否有关于 ECMA-335 或其他地方的具体实现的任何信息?

【问题讨论】:

次要注意:add 实际上有 3 个操作码,但这些是关于 行为(溢出/签名),而不是类型.正如usr 正确指出的那样:JIT 知道来自 IL 的类型。 【参考方案1】:

第 I 部分第 12 部分(例如来自 pdf)专门讨论了这一点,其中讨论了虚拟执行系统 ​​(VES):

如下所述,CIL 指令不指定其操作数类型。相反,CLI 保留 基于数据流和堆栈一致性要求的操作数类型的跟踪 如下面所描述的。例如,单个 add 指令将添加两个整数或两个浮点数 堆栈。

还有:

大多数处理数字的 CIL 指令从计算堆栈中获取操作数 (参见 §I.12.3.2.1),并且这些输入具有 VES 已知的关联类型。因此, 像add 这样的单个操作可以有任何数字数据类型的输入,尽管不是全部 指令可以处理操作数类型的所有组合。

I.12.1.4 的细节也相当多。

【讨论】:

【参考方案2】:

JIT 推断类型。无论如何,它必须这样做才能对您的程序进行类型检查。不需要为它们操作的类型参数化操作。堆栈的类型和大小可在 IL 指令序列中的任何位置计算。如果它们不可计算或不明确,则程序是无法验证的。

我相信 Java IL 做这件事的方式不同,但我可能弄错了。

【讨论】:

以上是关于如何在 CIL 中的堆栈上处理不同的类型的主要内容,如果未能解决你的问题,请参考以下文章

C# 到 CIL 装箱与 ToString 成本

了解 C 中的堆栈溢出处理

我的程序崩溃时如何自动生成堆栈跟踪

垃圾回收

ELK 堆栈和扩展

如何在堆栈上创建大小为 x 的数组并将 scanf 值放入其中