[讨论] Hotspot中的内联方法
huxi
2011-06-16
关于内联方法的说明Oracle有介绍,但是经过测试,我发现-XX+PrintInlining参数有点疑问。
1.6.0_25-ea-fastdebug" Java(TM) SE Runtime Environment (build 1.6.0_25-ea-fastdebug-b01) Java HotSpot(TM) Client VM (build 20.0-b08-fastdebug, mixed mode) public class Test { public final int foo() { return 65538; } public static void main(String args[]){ Test t = new Test(); System.out.println(t.foo()); } } java -Xcomp -XX:+PrintInlining org/dothwinds/test/ Test > log.log @ 4 org.dothwinds.test.Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) @ 12 org.dothwinds.test.Test::foo (3 bytes) 可以看到foo方法。接下来将foo方法不要内联。 java -Xcomp -XX:CompileCommand=dontinline,org/dothwinds/test/Test,foo -XX:+PrintInlining org/dothwinds/test/Test > log.log @ 4 org.dothwinds.test.Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) @ 12 org.dothwinds.test.Test::foo (3 bytes) 还是可以看到foo方法,这是为什么呢,难道PrintInlining这个参数会忽略掉dontinline么?生成出来的汇编代码我也比较了,除了地址不同外,其它的均相同,我就不贴出汇编代码了。难道dontinline不能反映出实际的效果么? |
|
RednaxelaFX
2011-06-16
很明显你在用HotSpot Client VM,也就是说在工作的JIT编译器是C1(client compiler)。
嗯…C1在这点上确实是有问题。C2就会检查dontinline,但C1目前不会。 我在邮件列表问了,等HotSpot开发的回复吧:http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2011-June/005773.html 要修这个行为很简单,在hotspot/src/share/vm/c1/c1_GraphBuilder.cpp里, bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { // Clear out any existing inline bailout condition clear_inline_bailout(); if (callee->should_exclude()) { // callee is excluded INLINE_BAILOUT("excluded by CompilerOracle") } else if (!callee->can_be_compiled()) { // callee is not compilable (prob. has breakpoints) INLINE_BAILOUT("not compilable") } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { // intrinsics can be native or not return true; } else if (callee->is_native()) { // non-intrinsic natives cannot be inlined INLINE_BAILOUT("non-intrinsic native") } else if (callee->is_abstract()) { INLINE_BAILOUT("abstract") } else { return try_inline_full(callee, holder_known); } } 改成: bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { // Clear out any existing inline bailout condition clear_inline_bailout(); if (callee->should_exclude()) { // callee is excluded INLINE_BAILOUT("excluded by CompilerOracle") } else if (callee->should_not_inline()) { // callee is tagged as dontinline INLINE_BAILOUT("dontinline by CompilerOracle") } else if (!callee->can_be_compiled()) { // callee is not compilable (prob. has breakpoints) INLINE_BAILOUT("not compilable") } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { // intrinsics can be native or not return true; } else if (callee->is_native()) { // non-intrinsic natives cannot be inlined INLINE_BAILOUT("non-intrinsic native") } else if (callee->is_abstract()) { INLINE_BAILOUT("abstract") } else { return try_inline_full(callee, holder_known); } } 你可以试试自己build一个fastdebug的HotSpot VM来跑这个测试。build的方法在以前的帖里说过:http://rednaxelafx.iteye.com/blog/875957 |
|
huxi
2011-06-16
多谢撒迦了,之前我在ubuntu11.04下build HotSpot VM有问题,build不过去,不知道有没有成功的童鞋,等我回去搞一个Xubuntu10.10,搞一个跟你一样的环境build。
|
|
IcyFenix
2011-06-16
我是ubuntu10.04,除了撒迦提到的要make两次的问题之外,一切都非常顺利。
倒是windows版的,原本linux下一条apt-get命令完成的事情,在windows下抓到吐血,依赖的东西还比linux大几百倍 |
|
RednaxelaFX
2011-06-16
huxi 写道 多谢撒迦了,之前我在ubuntu11.04下build HotSpot VM有问题,build不过去,不知道有没有成功的童鞋,等我回去搞一个Xubuntu10.10,搞一个跟你一样的环境build。
Ubuntu 10.10系列里无论是Ubuntu/XUbuntu/KUbuntu应该都差不多吧。 反正我是用不惯Unity界面所以没有升级到11.04。 IcyFenix 写道 我是ubuntu10.04,除了撒迦提到的要make两次的问题之外,一切都非常顺利。
倒是windows版的,原本linux下一条apt-get命令完成的事情,在windows下抓到吐血,依赖的东西还比linux大几百倍 要不要贡献一下你的Windows上build出OpenJDK的经验?或者至少放点小料来勾引一下人家买书也好,哈哈哈 make两次的问题主要是跟X相关的,跟VM部分无关。像我平时工作只需要build出HotSpot VM出来,从来都非常顺利,完全没问题。 |
|
huxi
2011-06-16
其实那天build出错了,我想拿出来给大家看看来的,后来一想因为这点事耽误大家时间有点过意不去,所以就没拿出来,还是换个Xubuntu来build吧。我也用不惯Unity,所以现在基本都用Ubuntu经典的界面。
To:IcyFenix,有没有亲笔签名的书售啊? |
|
RednaxelaFX
2011-06-16
huxi 写道 To:IcyFenix,有没有亲笔签名的书售啊?
就是,说来我也求个亲笔签名>_< |
|
IcyFenix
2011-06-16
RednaxelaFX 写道 要不要贡献一下你的Windows上build出OpenJDK的经验?或者至少放点小料来勾引一下人家买书也好,哈哈哈 '周末把那部分整理一下发出来。题目就叫做“正常人都不会选用的OpenJDK编译”好了。 huxi 写道 有没有亲笔签名的书售啊? 只是书不经过我手,从书商直接寄,没机会签啦。 RednaxelaFX 写道 就是,说来我也求个亲笔签名 这个木有问题。反正你那本从我这里寄出的。 |
|
RednaxelaFX
2011-06-17
简单验证了一下。用我之前那个XUbuntu 10.10虚拟机里的JDK 6 update 23来实验。
这个是今天重新build的一个干净版本的JDK6u23: rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -version java version "1.6.0-internal-fastdebug" Java(TM) SE Runtime Environment (build 1.6.0-internal-fastdebug-rednaxelafx_17_jun_2011_01_29-b00) Java HotSpot(TM) Client VM (build 19.0-b09-fastdebug, mixed mode) rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -Xcomp -XX:CompileCommand=dontinline,*Test,foo -XX:+PrintCompilation -XX:+PrintInlining Test > complog.log 跑出来的日志里确实可以看到main()方法内联了foo()方法。 211 b Test::main (19 bytes) @ 4 Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) @ 12 Test::foo (3 bytes) 然后按我前面回帖提到的方式修改了c1_GraphBuilder.cpp之后再build一次, rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -Xcomp -XX:CompileCommand=dontinline,*Test,foo -XX:+PrintCompilation -XX:+PrintInlining Test > complog_m.log 这次可以看到编译日志的输出变成这样了: 211 b Test::main (19 bytes) @ 4 Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) - @ 12 Test::foo (3 bytes) dontinline by CompilerOracle 也就是说成功的阻止了foo()的内联。 问题解决,撒花 ^_^ |
|
huxi
2011-06-17
RednaxelaFX 写道 简单验证了一下。用我之前那个XUbuntu 10.10虚拟机里的JDK 6 update 23来实验。
这个是今天重新build的一个干净版本的JDK6u23: rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -version java version "1.6.0-internal-fastdebug" Java(TM) SE Runtime Environment (build 1.6.0-internal-fastdebug-rednaxelafx_17_jun_2011_01_29-b00) Java HotSpot(TM) Client VM (build 19.0-b09-fastdebug, mixed mode) rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -Xcomp -XX:CompileCommand=dontinline,*Test,foo -XX:+PrintCompilation -XX:+PrintInlining Test > complog.log 跑出来的日志里确实可以看到main()方法内联了foo()方法。 211 b Test::main (19 bytes) @ 4 Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) @ 12 Test::foo (3 bytes) 然后按我前面回帖提到的方式修改了c1_GraphBuilder.cpp之后再build一次, rednaxelafx@vbox:~/experiment/test_c1_dontinline$ java -client -Xcomp -XX:CompileCommand=dontinline,*Test,foo -XX:+PrintCompilation -XX:+PrintInlining Test > complog_m.log 这次可以看到编译日志的输出变成这样了: 211 b Test::main (19 bytes) @ 4 Test::<init> (5 bytes) @ 1 java.lang.Object::<init> (1 bytes) - @ 12 Test::foo (3 bytes) dontinline by CompilerOracle 也就是说成功的阻止了foo()的内联。 问题解决,撒花 ^_^ 眼泪哗哗地。。身体是革命的本钱啊,你这个夜猫子。 |