为什么在基于堆栈的IL字节码中有局部变量

丹尼尔·AA·佩尔斯迈克:

在基于堆栈的中间语言(例如CIL或Java字节码)中,为什么会有局部变量?一个人只能使用堆栈。对于手工制作的IL来说可能并不那么容易,但是编译器肯定可以做到。但是我的C#编译器却没有。

堆栈和局部变量都是方法专用的,并且在方法返回时超出范围。因此,它与方法外部(从另一个线程)可见的副作用没有任何关系。

如果我是正确的,那么在生成机器代码时,JIT编译器将消除负载并存储到堆栈插槽和局部变量中,因此JIT编译器也看不到需要局部变量。

另一方面,即使在启用优化的情况下进行编译,C#编译器也会为局部变量生成加载和存储。为什么?


例如,以下人为设计的示例代码:

static int X()
{
    int a = 3;
    int b = 5;
    int c = a + b;
    int d;
    if (c > 5)
        d = 13;
    else
        d = 14;
    c += d;
    return c;
}

使用C#编译并进行优化后,它会产生:

    ldc.i4.3        # Load constant int 3
    stloc.0         # Store in local var 0
    ldc.i4.5        # Load constant int 5
    stloc.1         # Store in local var 1
    ldloc.0         # Load from local var 0
    ldloc.1         # Load from local var 1
    add             # Add
    stloc.2         # Store in local var 2
    ldloc.2         # Load from local var 2
    ldc.i4.5        # Load constant int 5
    ble.s label1    # If less than, goto label1
    ldc.i4.s 13     # Load constant int 13
    stloc.3         # Store in local var 3
    br.s label2     # Goto label2
label1:
    ldc.i4.s 14     # Load constant int 14
    stloc.3         # Store in local var 3
label2:
    ldloc.2         # Load from local var 2
    ldloc.3         # Load from local var 3
    add             # Add
    stloc.2         # Store in local var 2
    ldloc.2         # Load from local var 2
    ret             # Return the value

注意加载并存储到四个局部变量。我可以编写完全相同的操作(不考虑明显的常量传播优化),而无需使用任何局部变量。

    ldc.i4.3        # Load constant int 3
    ldc.i4.5        # Load constant int 5
    add             # Add
    dup             # Duplicate top stack element
    ldc.i4.5        # Load constant int 5
    ble.s label1    # If less than, goto label1
    ldc.i4.s 13     # Load constant int 13
    br.s label2     # Goto label2
label1:
    ldc.i4.s 14     # Load constant int 14
label2:
    add             # Add
    ret             # Return the value

在我看来,这是正确的,而且更短,更有效。那么,为什么基于堆栈的中间语言具有局部变量呢?为什么优化的编译器会如此广泛地使用它们?

卢塞罗:

根据情况的不同,尤其是在涉及调用而参数必须重新排序以匹配调用的情况下,如果您没有可使用的寄存器或变量,那么单纯的堆栈是不够的。如果您想只使用此堆栈,则需要附加的堆栈操作能力,例如交换/交换堆栈顶部两个项的功能。

最后,虽然在这种情况下可能将所有内容表示为基于纯堆栈的方法,但它可能会增加代码的整体复杂性,使其膨胀并使其更难以优化(局部变量是实现此目标的理想选择)缓存在寄存器中)。

还要记住,在.NET中,您可以通过引用传递参数,如何在没有局部变量的情况下为该方法调用创建IL?

bool TryGet(int key, out string value) {}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java字节码:局部变量表与堆栈计算

来自分类Java

为什么在Java字节码方法不是最经济的是使用的局部变量的数量?

来自分类Java

Java字节码中的局部变量

来自分类Dev

为什么要保留局部变量的堆栈空间?

来自分类Dev

为什么我的函数局部变量之间在堆栈中没有存储空间?

来自分类Java

访问最终的局部变量时,为什么在Java中有此InstantiationException?

来自分类Dev

为什么堆栈帧中局部变量数组的每个插槽都是4个字节,而不是JVM中的1个字节?

来自分类Java

如何从Java字节码中判断局部变量是否为“最终”?(与BCEL有关)

来自分类Java

JVM字节码,如何找到局部变量的类型?

来自分类Dev

为什么我的局部变量没有被覆盖?

来自分类Dev

为什么分配给堆栈中的局部变量的内存比C ++所需的内存多?

来自分类Dev

为什么函数局部变量和参数被压入堆栈?

来自分类Dev

将“ this”存储在struct方法的局部变量中有什么优势?

来自分类Dev

使用局部变量有什么好处?

来自分类Dev

将堆栈用于局部变量的背后的想法是什么?

来自分类Dev

什么时候创建局部变量堆栈?

来自分类Java

为什么增强的for循环的局部变量必须是局部的?

来自分类Dev

为什么在有局部变量的情况下调用全局变量?

来自分类Dev

为什么在从Visual Studio调试ASP.NET Core源代码时无法在堆栈中间看到局部变量

来自分类Dev

为什么解释器调用变量ia局部变量

来自分类Java

为什么在case语句中变量不是局部变量?

来自分类Dev

java.lang.VerifyError:字节码检测后局部变量类型错误

来自分类Dev

为什么eclipse会说即使使用了局部变量也没有使用?

来自分类Dev

为什么按值传递局部变量有效?

来自分类Java

为什么有人在Java中将局部变量和方法参数标记为“最终”?

来自分类Dev

Span <T>不能是嵌套的局部变量。为什么会有限制?

来自分类Dev

为什么JVM为什么将堆用于对象和静态变量,将堆栈用于局部变量和函数调用?

来自分类Dev

为什么局部变量不超出范围?

来自分类Java

为什么局部变量在Java中是线程安全的

Related 相关文章

  1. 1

    Java字节码:局部变量表与堆栈计算

  2. 2

    为什么在Java字节码方法不是最经济的是使用的局部变量的数量?

  3. 3

    Java字节码中的局部变量

  4. 4

    为什么要保留局部变量的堆栈空间?

  5. 5

    为什么我的函数局部变量之间在堆栈中没有存储空间?

  6. 6

    访问最终的局部变量时,为什么在Java中有此InstantiationException?

  7. 7

    为什么堆栈帧中局部变量数组的每个插槽都是4个字节,而不是JVM中的1个字节?

  8. 8

    如何从Java字节码中判断局部变量是否为“最终”?(与BCEL有关)

  9. 9

    JVM字节码,如何找到局部变量的类型?

  10. 10

    为什么我的局部变量没有被覆盖?

  11. 11

    为什么分配给堆栈中的局部变量的内存比C ++所需的内存多?

  12. 12

    为什么函数局部变量和参数被压入堆栈?

  13. 13

    将“ this”存储在struct方法的局部变量中有什么优势?

  14. 14

    使用局部变量有什么好处?

  15. 15

    将堆栈用于局部变量的背后的想法是什么?

  16. 16

    什么时候创建局部变量堆栈?

  17. 17

    为什么增强的for循环的局部变量必须是局部的?

  18. 18

    为什么在有局部变量的情况下调用全局变量?

  19. 19

    为什么在从Visual Studio调试ASP.NET Core源代码时无法在堆栈中间看到局部变量

  20. 20

    为什么解释器调用变量ia局部变量

  21. 21

    为什么在case语句中变量不是局部变量?

  22. 22

    java.lang.VerifyError:字节码检测后局部变量类型错误

  23. 23

    为什么eclipse会说即使使用了局部变量也没有使用?

  24. 24

    为什么按值传递局部变量有效?

  25. 25

    为什么有人在Java中将局部变量和方法参数标记为“最终”?

  26. 26

    Span <T>不能是嵌套的局部变量。为什么会有限制?

  27. 27

    为什么JVM为什么将堆用于对象和静态变量,将堆栈用于局部变量和函数调用?

  28. 28

    为什么局部变量不超出范围?

  29. 29

    为什么局部变量在Java中是线程安全的

热门标签

归档