[讨论] 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()的内联。
问题解决,撒花 ^_^


眼泪哗哗地。。身体是革命的本钱啊,你这个夜猫子。
Global site tag (gtag.js) - Google Analytics