2

简单的好奇,这段代码

    private const long constLong = 16;
    private static long instanceLong = 16;

    static long constTest()
    { 
        long i = 4;
        return i + constLong;
    }

    static long instanceTest()
    {
        long i = 4;
        return i + instanceLong;
    }

产生这个 IL:

.field private static literal int64 constLong = int64(16)
.field private static int64 instanceLong

.method private hidebysig static int64 constTest () cil managed 
{
    // Method begins at RVA 0x2068
    // Code size 9 (0x9)
    .maxstack 2
    .locals init (
        [0] int64 i
    )

    IL_0000: ldc.i4.4
    IL_0001: conv.i8
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: ldc.i4.s 16
    IL_0006: conv.i8
    IL_0007: add
    IL_0008: ret
} // end of method Program::constTest

.method private hidebysig static int64 instanceTest () cil managed 
{
    // Method begins at RVA 0x2080
    // Code size 11 (0xb)
    .maxstack 2
    .locals init (
        [0] int64 i
    )

    IL_0000: ldc.i4.4
    IL_0001: conv.i8
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: ldsfld int64 ConsoleApplication1.Program::instanceLong
    IL_0009: add
    IL_000a: ret
} // end of method Program::instanceTest

为什么 constTest() 有ldc.i4.s

    IL_0004: ldc.i4.s 16
    IL_0006: conv.i8

而不是ldc.i8

    IL_0004: ldc.i8 16

因为现在 constTest() 需要做一个conv.i8

就像我说的,这纯粹是好奇。

4

3 回答 3

3

这种方式更紧凑,请参阅标签以获取提示。

IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: stloc.0

这需要一个字节ldc.i4.4和一个字节conv.i8:总共两个字节。

IL_0004: ldc.i4.s 16
IL_0006: conv.i8
IL_0007: add

这需要两个字节ldc.i4.s16一个字节conv.i8:总共三个字节。

ldc.i8 16指令占用 1 个字节,操作数(16)占用 4 个字节:总共 5 个字节。

但请记住,更短的 IL 并不意味着一旦它被 JIT'ed(或 AOT'ed)更快(或更慢)原生。

于 2013-04-07T17:16:17.033 回答
1

请记住,您查看的是 IL,而不是最终的机器代码。IL 的目标是尽可能接近地捕获代码/程序员意图,以便 JITTER 可以执行最佳优化。

如果 JITTER 正在执行此操作,则会出现问题,但编译器执行此操作时无需担心。

于 2013-04-07T17:12:33.233 回答
1

简单的答案是“这就是编译器生成代码的方式”。您必须记住,实际生成的本机代码可以在 32 位或 64 位 CPU 上运行。IL 被编译为目标指令集,因此:

  ldc.i4 4
  conv.i8

很可能成为 64 位 CPU 上的单一负载。

于 2013-04-07T17:15:27.510 回答