有人能解释MSIL的几行?为什么它从计算堆栈的值移动到一个局部变量,只是它立即采取行动倒流,回到了?

下面的MSIL代码加载一个参数(字符串),调用一个方法,它返回布尔,然后返回bool值。我不明白的是为什么它会调用stloc.0存储在一个局部变量的方法的返回值,然后执行一个明确无条件控制转移到第二天标记线(似乎没有必要),只值向右移动回至返回之前评价堆栈。

.maxstack 1
.locals init ([0] bool CS$1$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: call bool FuncNameNotImporant::MethodNameNotImporant(string)
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 

在它为什么这是执行某种类型的检查,以确保评估堆栈上的价值我最好的猜测居然是返回之前一个布尔值。但我毫无头绪显式跳转到很下一行;我的意思是,是不是去那里呢?该方法的C#源代码只是一个线路,它返回该方法的结果。

有帮助吗?

解决方案

如果你在调试器打开此功能,与在调试模式下编译的代码:

bool foo(string arg)
{
    return bar(arg);
}

有3个断点可以设置:

  1. 在该函数的开括号。
  2. 在 “返回” 线。
  3. 在该函数的右大括号。
  4. 设置在左括号一个破发点的意思是“休息的时候这个功能获取的被称为”。这就是为什么有是在方法的开头no-op指令。当断点设置在左括号调试器实际上是设置它的无操作。

    设置在右括号中断点的意思是“休息时这个函数退出”。为了让这种情况发生的功能需要有一个单一的返回指令,在它的IL,其中破发点可以设置。编译器使得能够通过使用临时变量来存储返回值,并转换

    return retVal;
    

    $retTmp = retVal;
    goto exit;
    

    和随后在该方法的底部注入以下代码:

    exit:
    return $ret;
    

    此外,当在调试模式下,编译器是愚蠢的有关代码他们generation.They基本上执行类似:

    GenerateProlog();
    foreach (var statement in statements)
    {
        Generate(statement);
    }
    GenerateEpilog();
    

    在你的情况,你所看到的:

    return foo(arg);
    

    被翻译成:

    ; //this is a no-op
    bool retTemp = false;
    retTemp = foo(arg);
    goto exit;
    exit:
    return retTemp;
    

    如果编译器在做一个“滑动窗口优化”它可能是能够查看这些代码,实现有一些redundency.However,编译器一般不做,在调试模式。编译器优化可以做的事情一样消除变量,并指令重新排序,这使得调试困难。由于调试版本的目的是使调试,它不会是良好接入优化。

    在一个发布版本,代码不会像这一点。这是因为编译器不引入特殊代码,以使在开启和关闭括号,刚刚离开下面进行编译断点:

    return bar(arg);
    

    这最终看起来非常简单。

    有一点需要注意,然而,就是我不认为C#编译器不会多滑动窗口的优化,即使在零售版本。那是因为大多数这些优化依赖于底层的处理器架构,并因此由JIT编译器来完成。在做优化,甚至是处理器无关的那些,在C#编译器可以阻碍JIT的优化代码的能力(这在寻找由非优化的代码生成生成模式,如果它看到大量优化的IL它可以得到困惑)。所以平时manged代码编译器不做它们。它做了一些“昂贵的东西”(该JIT不希望在运行时做的),像死代码检测,并现场变量分析,但他们不应对滑动窗口优化解决的问题。

其他提示

您在调试或发行模式下编译?在释放模式获得:

.method private hidebysig static bool Test1(string arg) cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: call bool FuncNameNotImportant::MethodNameNotImportant(string)
    L_0006: ret 
}

您所看到的分支可能是用于调试器支持。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top