因此,我知道许多C风格的语言都有减量(--)和递增(++)运算符,并允许在整个表达式求值之前或之后发生突变。
当返回值发生后增量时会发生什么?我不是在问行为,而是问实现。
给定一个虚拟机(如JavaScript/JVM)或物理机(如编译的C++),生成的操作码是否如下所示?(假设基于堆栈的参数/返回。)
int x = 4, y = 8;
return f(++a) + y++;变成这样:(也许?)
LOAD 4 A
LOAD 8 B
INC A
PUSH A
CALL F
POP INTO C
ADD C BY B
INC B
RET C如果是这样的话,当表达式变得复杂时,这些语言中的这些操作如何决定在哪里嵌入增量?
发布于 2013-03-17 19:42:50
一旦优化了代码(通过C++编译器或JIT),我希望得到类似于以下内容的结果:
来源:
int x = 4, y = 8;
return f(++x) + y++;使用说明:
PUSH 5
CALL f
POP INTO A
ADD 8 to A
RET A我列出的指令是正确的(除非我犯了一些愚蠢的错误),它们只需要我知道优化器能够进行的代码转换。基本上,不计算未使用的结果,而在优化时计算具有已知结果的操作。
在特定的体系结构上,很可能有一种更有效的方法来实现它,在这种情况下,优化器很有可能知道并使用它。优化器经常超出我的预期,因为我不是一个专业的汇编程序员。在这种情况下,调用约定很可能为函数f和以下代码中的返回值指定了相同的位置。因此,可能不需要任何POP --返回寄存器/堆栈位置可以只添加8。此外,如果函数f是内联的,那么优化将在内联之后应用。
例如,如果f返回input * 2,那么整个函数可能会优化为:
RET 18发布于 2013-03-17 19:28:22
Java运行时与您的源代码甚至字节码相去甚远。一旦对一个方法进行了JIT编译,得到的机器码就会得到积极的优化。但更重要的是,这种优化的细节远远超出了任何规范。如果您对它感兴趣,您可能会深入研究像HotSpot这样的实现,但您从中学到的所有东西都是特定于平台、版本、内部版本号、JVM启动参数,甚至是JVM的单独运行。
发布于 2013-03-17 19:46:02
您可以确切地看到编译器使用javap生成的内容。例如:
int x = 4, y = 8;
return f(++x) + y++;被编译成这个字节码序列:
0: iconst_4
1: istore_1
2: bipush 8
4: istore_2
5: aload_0
6: iinc 1, 1
9: iload_1
10: invokevirtual #2; //Method f:(I)I
13: iload_2
14: iinc 2, 1
17: iadd
18: ireturn当然,这取决于JVM如何将其转换为汇编程序-有关如何在OpenJDK 7中查看结果的信息,请参阅Disassemble Java JIT compiled native bytecode。
https://stackoverflow.com/questions/15460199
复制相似问题