24 | 字段访问相关优化
郑雨迪
该思维导图由 AI 生成,仅供参考
在上一篇文章中,我介绍了逃逸分析,也介绍了基于逃逸分析的优化方式锁消除、栈上分配以及标量替换等内容。
其中的标量替换,可以看成将对象本身拆散为一个个字段,并把原本对对象字段的访问,替换为对一个个局部变量的访问。
举个例子,上面这段代码中的bar方法,经过逃逸分析以及标量替换后,其优化结果如下所示。(确切地说,是指所生成的 IR 图与下述代码所生成的 IR 图类似。之后不再重复解释。)
由于 Sea-of-Nodes IR 的特性,局部变量不复存在,取而代之的是一个个值。在例子对应的 IR 图中,返回节点将直接返回所输入的参数。
经过标量替换的bar方法
下面我列举了bar方法经由 C2 即时编译生成的机器码(这里略去了指令地址的前 48 位)。
在 X86_64 的机器码中,每当使用 call 指令进入目标方法的方法体中时,我们需要在栈上为当前方法分配一块内存作为其栈桢。而在退出该方法时,我们需要弹出当前方法所使用的栈桢。
由于寄存器 rsp 维护着当前线程的栈顶指针,因此这些操作都是通过增减寄存器 rsp 来实现的,即上面这段机器码中偏移量为 0x06a0 以及 0x06ae 的指令。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
基于逃逸分析的优化方式是本文的重点,其中包括标量替换和字段访问优化。通过标量替换,对象字段的访问被替换为对局部变量的访问,从而简化代码并提高执行效率。文章还详细介绍了即时编译器对字段访问的优化策略,包括缓存字段存储节点的值、替换字段读取节点、处理volatile字段和锁操作等情况。通过优化实例字段和静态字段的访问,即时编译器能够减少总的内存访问次数,提升程序性能。此外,死代码消除也是关键内容之一,包括局部变量的死存储消除以及不可达分支消除。这些优化方式和消除策略对于理解Java虚拟机的优化技术具有重要参考价值。文章内容深入浅出,为读者提供了深入了解即时编译器优化方式的机会。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(18)
- 最新
- 精选
- Void_seT因为x/y会有除0异常,这部分代码是否会被优化掉,不太确定,望老师指点。
作者回复: 对的,因为有除0异常所以编译器没法优化掉这个除法
2018-09-1417 - 小文同学老师,请问一下,读这个专栏有点像涨视野的感觉,暂时来说对我看代码提供了新的灵感,但目前只能听,没法提问,这种感觉是是因为我底子不够么?还是我实践得比较少?
作者回复: 按照自己的节奏学习就好啦,等以后遇到问题了也可以回来提问的。
2018-09-2010 - Scott"其中真正的安全点测试是 0x06ba 指令"应该是0x06b7指令
作者回复: 多谢指出!已修改!
2018-09-1424 - 永烁星光Return x+y ;
作者回复: 课后实践中的除法无法优化,因为可能存在除零异常。即时编译器需要判断除数是否为0
2018-09-143 - Scott这一篇洋洋洒洒,其实覆盖了更多后端优化的算法,是否可以罗列一下对应算法名称供参考?
作者回复: 我记得就叫read elimination和write elimination。第三节的是dead store elimination和partial redundancy elimination。 Graal的相关代码在PEReadEliminationClosure以及ReadEliminationClosure中。可以自行阅读。
2018-09-142 - 李二木感觉写代码的能力水平跟编译器优化工作量还是有点关系的。
作者回复: 一般我们写代码都会在保持代码可读性的同时,尽量减少编译器工作量
2018-09-142 - 李二木除法操作直接消除,返回return x+y; ?
作者回复: 消除不了,有位同学答出来了,有除零异常
2018-09-142 - 誓言的梦有除零的异常 是通过什么手段/机制知道 还是写死的除法不能优化 或者回不回是通过 检测当输入除数为0就不优化 输入不为0时才优化2018-12-196
- 剑八总结下来: 编绎器对于读取及存储指令的优化 对于读取,如果涉及一个堆对象同一个字段的多次读取,且不涉及该字段的写操作则会优化成方法执行中的缓存。只在第一次读取该对象字段时会从堆中取。会将该对象字段值缓存在局部变量表中。后面读取从这个地方取。这就涉及到一个多线程的可见性问题。如果想要去除可以设置为volatile或加lock,syncronized锁。 对于写操作,如果一个方法体对于一个变量的写是会覆盖的,则只会保留最后一个写操作。 还有一个优化则可以对于不可到达的分支代码进行消除,本质上都是减少不执行的代码,减少编绎成机器码后存储到code cache中的大小。2020-06-144
- test判断输入如果y为0则抛出异常,否则直接返回x+y2020-02-2323
收起评论