在基于堆栈的虚拟机中,带返回值的赋值表达式如何在汇编级别进行优化?

问题描述 投票:0回答:1

在 Java 和 C# 以及许多使用基于堆栈虚拟机的常见编程语言和运行时中,我们编写基本的赋值表达式就像这样简单:

a = 1;

编译器最初生成(伪)汇编代码(或中间语言),如下所示:

PUSHINT 1  # push 1 into the top of evaluation stack
DUP        # duplicate the top of evaluation stack
ST a       # store the value at the top of evaluation stack to variable a
DROP       # drop the top of evaluation stack

而不是

PUSHINT 1
ST a

我认为原因是,

a=1
是一个返回值为1的表达式。这用于连续赋值,例如
a=b=1
。然而,我们不能总是接受到处都是冗余的 DUP 和 DROP。

优化后的汇编代码中多余的DUP和DROP是如何自动删除的?

jvm llvm clr compiler-optimization intermediate-language
1个回答
0
投票

几乎所有基于堆栈的虚拟机都有所谓的堆栈帧 - 有关堆栈在某个时间点包含哪些值的信息。这就是为什么您不能在循环中将元素推入堆栈的原因 - 堆栈值需要与堆栈帧类型对齐。该堆栈帧又允许进行大量优化,但最简单的示例是将推送的值分配给表示堆栈空间的变量。我们可以这样做的原因是,由于堆栈帧声明,对于每次堆栈修改,我们都提前知道堆栈的结构。在你的情况下,这可能看起来像这样:

PUSHINT 1 -> stack1 = 1
DUP       -> stack2 = stack1
ST a      -> a = stack2
DROP      -> # do nothing

从这个形式中,无用的

stack1
stack2
可以很容易地被优化掉,我们只得到
a = 1

© www.soinside.com 2019 - 2024. All rights reserved.