本文主要是介绍【14】即时编译器的中间表达形式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
中间表达形式(IR)
-
编译器一般被分为前端和后端。
- 前端会对输入的程序进行词法分析、语法分析和语义分析,然后生成中间表达形式(IR);
- 后端对IR进行优化,生成目标代码
-
不考虑解释执行的话,Java源码到最终机器码实际上进行了两轮编译:
- 源码---->Java字节码(Java编译器)
- Java字节码----> 机器码(即时编译器)
-
JIT不需要重新进行词法、语法、语义分析,而是直接将Java字节码当做IR。
SSA IR
SSA:静态单赋值
这种IR的特点是每个变量只能被赋值一次,且只有在被赋值以后才能使用。
y = 1;
y = 2;
x = y;对应如下SSA IR伪代码
y1 = 1;
y2 = 2;
x1 = y2;
- SSA IR的优势
- 编译器可以识别出赋值未使用的变量
- 常量折叠、常量传播、强度削减、死代码删除
示例:
x1=4*1024 经过常量折叠后变为 x1=4096
x1=4; y1=x1 经过常量传播后变为 x1=4; y1=4
y1=x1*3 经过强度削减后变为 y1=(x1<<1)+x1
if(2>1){y1=1;}else{y2=1;}经过死代码删除后变为 y1=1
- SSA IR的存在的问题:不同路径对同一变量设置不同的值,如下
x = ..;
if (x > 0) {y = 0;
} else {y = 1;
}
x = y;解决思路,引入Phi函数(根据不同执行路径,选择不同的值)
x1 = ..;
if (x1 > 0) {y1 = 0;
} else {y2 = 1;
}
y3 = Phi(y1, y2);
x2 = y3;
总之,即时编译器会将 Java 字节码转换成 SSA IR。更确切的说,是一张包含控制流和数据流的 IR 图,每个字节码对应其中的若干个节点(注意,有些字节码并没有对应的 IR 节点)。然后,即时编译器在 IR 图上面进行优化。我们可以将每一种优化看成一个独立的图算法,它接收一个 IR 图,并输出经过转换后的 IR 图。整个编译器优化过程便是一个个优化串联起来的。
Sea of Nodes
HotSpot里的C2采用的是名为 Sea-of-nodes的SSA IR。它最大的特点是去除了变量的概念,直接采用变量所指向的值来进行运算。
这篇关于【14】即时编译器的中间表达形式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!