[inside hotspot] 汇编模板解释器(Template Interpreter)和字节码执行 (2)

使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintInterpreter -XX:+LogCompilation -XX:LogFile=file.log保存结果到文件,可以查看生成的这些例程。
随便举个例子,模板解释器特殊处理java.lang.Math里的很多数学函数,使用它们不需要建立通常意义的java栈帧,且使用sse指令可以得到极大的性能提升:

// hotspot\src\cpu\x86\vm\templateInterpreterGenerator_x86_64.cpp address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { // rbx,: Method* // rcx: scratrch // r13: sender sp if (!InlineIntrinsics) return NULL; // Generate a vanilla entry address entry_point = __ pc(); if (kind == Interpreter::java_lang_math_fmaD) { if (!UseFMA) { return NULL; // Generate a vanilla entry } __ movdbl(xmm0, Address(rsp, wordSize)); __ movdbl(xmm1, Address(rsp, 3 * wordSize)); __ movdbl(xmm2, Address(rsp, 5 * wordSize)); __ fmad(xmm0, xmm1, xmm2, xmm0); } else if (kind == Interpreter::java_lang_math_fmaF) { if (!UseFMA) { return NULL; // Generate a vanilla entry } __ movflt(xmm0, Address(rsp, wordSize)); __ movflt(xmm1, Address(rsp, 2 * wordSize)); __ movflt(xmm2, Address(rsp, 3 * wordSize)); __ fmaf(xmm0, xmm1, xmm2, xmm0); } else if (kind == Interpreter::java_lang_math_sqrt) { __ sqrtsd(xmm0, Address(rsp, wordSize)); } else if (kind == Interpreter::java_lang_math_exp) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dexp() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dexp)); } } else if (kind == Interpreter::java_lang_math_log) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dlog() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)); } } else if (kind == Interpreter::java_lang_math_log10) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dlog10() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog10()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10)); } } else if (kind == Interpreter::java_lang_math_sin) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dsin() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dsin()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); } } else if (kind == Interpreter::java_lang_math_cos) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dcos() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcos()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); } } else if (kind == Interpreter::java_lang_math_pow) { __ movdbl(xmm1, Address(rsp, wordSize)); __ movdbl(xmm0, Address(rsp, 3 * wordSize)); if (StubRoutines::dpow() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dpow()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dpow)); } } else if (kind == Interpreter::java_lang_math_tan) { __ movdbl(xmm0, Address(rsp, wordSize)); if (StubRoutines::dtan() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtan()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); } } else { __ fld_d(Address(rsp, wordSize)); switch (kind) { case Interpreter::java_lang_math_abs: __ fabs(); break; default: ShouldNotReachHere(); } __ subptr(rsp, 2*wordSize); // Round to 64bit precision __ fstp_d(Address(rsp, 0)); __ movdbl(xmm0, Address(rsp, 0)); __ addptr(rsp, 2*wordSize); } __ pop(rax); __ mov(rsp, r13); __ jmp(rax); return entry_point; }

我们关注java.lang.math.Pow()方法,加上-XX:+PrintInterpreter查看生成的例程:

else if (kind == Interpreter::java_lang_math_pow) { __ movdbl(xmm1, Address(rsp, wordSize)); __ movdbl(xmm0, Address(rsp, 3 * wordSize)); if (StubRoutines::dpow() != NULL) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dpow()))); } else { __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dpow)); } } ---------------------------------------------------------------------- method entry point (kind = java_lang_math_pow) [0x000001bcb62feaa0, 0x000001bcb62feac0] 32 bytes 0x000001bcb62feaa0: vmovsd 0x8(%rsp),%xmm1 0x000001bcb62feaa6: vmovsd 0x18(%rsp),%xmm0 0x000001bcb62feaac: callq 0x000001bcb62f19d0 0x000001bcb62feab1: pop %rax 0x000001bcb62feab2: mov %r13,%rsp 0x000001bcb62feab5: jmpq *%rax 0x000001bcb62feab7: nop 0x000001bcb62feab8: add %al,(%rax) 0x000001bcb62feaba: add %al,(%rax) 0x000001bcb62feabc: add %al,(%rax) 0x000001bcb62feabe: add %al,(%rax)

callq会调用hotspot\src\cpu\x86\vm\stubGenerator_x86_64.cpp的address generate_libmPow(),感兴趣的可以去看一下,这里就不展开了。

2.字节码的解释执行

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjpxz.html