[讨论] 有关 generate_normal_entry 问题请教各位大侠

huangriyan 2014-08-28
各大侠
小弟在看 OpenJDK HotSpot JVM 源码时,对方法 generate_normal_entry 有以下疑问:
1、返回的地址时  address entry_point = __ pc();。呢是不是说明在一般方法中,都会执行  address entry_point = __ pc();到 return entry_point 这部分代码。因为好像 call_stub 最终会call 这个地址。
2、如果第1点的理解是正确的,那么invoke java 方法时,岂不是在 call_stub与generate_normal_entry  分别执行两次这个方法?
RednaxelaFX 2014-09-02
首先楼主请参考一下一篇论文:Generation of Virtual Machine Code at Startup
HotSpot VM的模板解释器就如这篇论文所述,是在虚拟机启动时动态生成出来的。
HotSpot VM自带一个用C++实现的一个汇编器库,而模板解释器就是通过调用这个汇编器库生成出来的。
在HotSpot的平台相关部分代码里,有不少地方会有“__ xxx()”这样形式的代码。此时“__”多半是被define为:
_masm->

例如在此:http://hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/ded432e6064b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp#l48
这里_masm是指向一个汇编器实例的变量,而后面的xxx()则是该实例上的方法,用于生成“xxx”对应的机器码。例如说在HotSpot的x86平台代码里,
__ addl(rcx, rax);

经过C++预编译的宏展开就变成:
_masm->addl(rcx, rax);

这样的代码就会向_masm所指向的汇编器实例所持有的CodeBuffer里生成下面汇编所对应的机器码(例子用Intel语法):
add  rcx, rax


再次强调,对汇编器库的调用只是用来生成机器码,后面实际实现功能的是那些动态生成回来的机器码而不是调用汇编器库的C++代码。所以回到楼主的问题,generate_normal_entry()只在虚拟机启动阶段被调用,等到HotSpot VM真正开始解释执行Java代码时,CallStub的跳转目标是generate_normal_entry()所生成出来的机器码,而不是generate_normal_entry()这个C++函数自身。

address entry_point = __ pc();

这句代码用于记录当前CodeBuffer生成到的位置的地址。在生成一段机器码的时候,先这么执行一句就把这段机器码的起始地址拿到了。于是最后返回出去的就是这个起始地址,用于作为后续调用的目标地址。

在OpenJDK 7u的HotSpot的x86-64版本上,generate_normal_entry()的定义在:
http://hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/ded432e6064b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp#l1290
这个函数负责生成解释器的“普通方法入口”。关于HotSpot解释器的各种入口,请参考HLLVM群组之前的一帖讨论:http://hllvm.group.iteye.com/group/topic/40255

楼主如果读了上面的论文和讨论帖还有疑问欢迎继续发问讨论 ^_^
Global site tag (gtag.js) - Google Analytics