深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
27874 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么我们要学习Java虚拟机?
免费
模块一:Java虚拟机基本原理 (12讲)
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
模块二:高效编译 (12讲)
【工具篇】 常用工具介绍
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
模块三:代码优化 (10讲)
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
模块四:黑科技 (3讲)
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
尾声 (1讲)
尾声 | 道阻且长,努力加餐
深入拆解Java虚拟机
登录|注册

18 | 即时编译器的中间表达形式

郑雨迪 2018-08-31
在上一章中,我利用了程序控制流图以及伪代码,来展示即时编译器中基于 profile 的优化。不过,这并非实际的优化过程。

1. 中间表达形式(IR)

在编译原理课程中,我们通常将编译器分为前端和后端。其中,前端会对所输入的程序进行词法分析、语法分析、语义分析,然后生成中间表达形式,也就是 IR(Intermediate Representation )。后端会对 IR 进行优化,然后生成目标代码。
如果不考虑解释执行的话,从 Java 源代码到最终的机器码实际上经过了两轮编译:Java 编译器将 Java 源代码编译成 Java 字节码,而即时编译器则将 Java 字节码编译成机器码。
对于即时编译器来说,所输入的 Java 字节码剥离了很多高级的 Java 语法,而且其采用的基于栈的计算模型非常容易建模。因此,即时编译器并不需要重新进行词法分析、语法分析以及语义分析,而是直接将 Java 字节码作为一种 IR。
不过,Java 字节码本身并不适合直接作为可供优化的 IR。这是因为现代编译器一般采用静态单赋值(Static Single Assignment,SSA)IR。这种 IR 的特点是每个变量只能被赋值一次,而且只有当变量被赋值之后才能使用。
y = 1;
y = 2;
x = y;
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(10)

  • MissSunday
    看不太懂。哈哈哈...可能基础还不到这个水平吧,多看多思考吧。
    2018-12-09
    6
  • ext4
    除了你上面提到的内存依赖,我看到C2的ideal graph里面还有一种依赖叫做I/O dependency,这个在Graal的graph里似乎也没有了。可以解释一下C2的这个I/O dependency是做什么的,以及Graal是如何替代这种依赖的表示的么?

    作者回复: 首先这些dependency都是为了scheduling服务的,也就是把图序列化为指令序列,图节点中的相互依赖会让它们拥有先后关系。

    个人理解哈,原本的IO dependency就是IO顺序,Cliff Click大神的论文中说的是没有内存映射的IO访问。现在C2应该用来泛指非内存访问的JVM状态。

    Graal里这种额外的依赖关系都是用控制流先后顺序来表达的。

    2018-08-31
    2
  • 夜行观星
    看懂这篇文章,已经是一年之后,时间真快
    2019-11-19
  • 鱼肚
    原本里的 IGV 用不了,用这个 https://github.com/oracle/graal/releases/tag/idealgraphvisualizer-543
    2019-09-03
  • neohope
    想问一下老师,idealgraphvisualizer中,有没有办法看到全局的IR图?开启后,好像有很多次优化,每次都只能看到一部分哦。

    此外:
    1、官网下载的idealgraphvisualizer是2011年版本,没法用,要用直接在github上下载的版本
    2、idealgraphvisualizer当前版本,好像只支持JDK1.8?
    3、从graal官网下载的版本只有JDK1.8,下载了也没有用。直接下载Oracle JDK11就可以了
    4、最后例子的Demo,JDK11参数要调整一下:
    java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:CompileCommand=dontinline,"CompilationTest.hash()" -Dgraal.Dump=:3 -Dgraal.OptDeoptimizationGrouping=false CompilationTest
    5、前面两个例子,需要用Debug版本的JDK。最后一个不需要。
    2019-09-02
    1
  • 樱小路依然
    呃,感觉有点不懂、
    1.老师先说前端编译器将Java代码优化为IR
    2.Java编译器将源代码编译为Java字节码
    3.即时编译器将Java字节码当做一种IR
    4.Java字节码并不适合作为可供优化的IR,因为其为 SSA IR,采用静态单赋值的方式

    然而,后面老师又说:总之,即时编译器会将Java字节码转化为SSA IR。

    请问到底是 Java编译器将Java源代码编译、转化为 SSA IR
    还是即时编译器将Java字节码转换为SSA IR?
    2019-08-22
  • Jthan
    好靠前
    2019-08-22
  • 草戊
    有好多编译原理的东西
    2019-05-21
  • likun
    你好 我这边找不到bebug版本的jdk10,好像无法查看ir图

    作者回复: 导出Graal IR不用debug版本的JDK

    2018-10-22
  • code-artist
    IR图有点看不懂。基本块是根据什么原则划分的? 有些块有start,begin, end等等,有些块却没有? 为什么GVN代码中,都是判断a,b是否大于0,图中B3来了一个Merge节点?

    作者回复: 先说一下,这个是Graal的IR。

    基本块的划分规则是根据其定义来的,即最长的,顺序执行的节点集。

    start begin end是为了标注基本块的起始和结尾,便于优化,没有其他实际意义。

    merge节点可以看成控制流交汇的节点,在Graal里就是用来挂phi节点的。最后有两个return而没有merge,实际上是另外一个优化code duplicati,将原本的merge优化掉,生成两条独立程序路径。在这两条路径中,b的值是唯一的,而不是一个phi方法。

    2018-09-03
收起评论
10
返回
顶部