正如 Headers 所述,为什么OpenJDK JVM不会在Windows x86上发出预取指令?见OpenJDK Mercurial @ http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c49dcaf78a65/src/os_cpu/windows_x86/vm/prefetch_windows_x86.inline.hpp
inline void Prefetch::read (void *loc, intx interval) {}
inline void Prefetch::write(void *loc, intx interval) {}
没有评论,我发现除了源代码之外没有其他资源 . 我问,因为它适用于Linux x86,请参阅http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c49dcaf78a65/src/os_cpu/linux_x86/vm/prefetch_linux_x86.inline.hpp
inline void Prefetch::read (void *loc, intx interval) {
#ifdef AMD64
__asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
#endif // AMD64
}
inline void Prefetch::write(void *loc, intx interval) {
#ifdef AMD64
// Do not use the 3dnow prefetchw instruction. It isn't supported on em64t.
// __asm__ ("prefetchw (%0,%1,1)" : : "r" (loc), "r" (interval));
__asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
#endif // AMD64
}
2 回答
你引用的文件都有asm代码片段(inline assembler),一些C / C软件在自己的代码中使用(如apangin, the JVM expert pointed,主要是GC代码) . 实际上存在差异:x86_64热点的Linux,Solaris和BSD变体在热点中有预取,而Windows禁用/未实现这是部分奇怪的,部分无法解释的原因,它也可能使JVM位(某些百分比;更多)没有硬件预取的平台)在Windows上速度较慢,但仍无法帮助销售更多针对Sun / Oracle的solaris / solaris付费支持 Contract . Ross also guessed MS C编译器可能不支持内联asm语法,但
_mm_prefetch
应该(谁将打开JDK bug来添加它to the file?) .JVM热点是JIT,JIT作为字节由JIT发出(生成)JITted代码(虽然JIT可以将代码从其自己的函数复制到生成的代码中或者发出对支持函数的调用,但是预取是作为字节发出的 . 热点) . 我们怎样才能发现它是如何排放的?简单的在线方式是找到一些jdk8u的在线可搜索副本(或更好的cross-reference like metager),例如在github:https://github.com/JetBrains/jdk8u_hotspot上,并搜索prefetch或prefetch emit或prefetchr或lir_prefetchr . 有一些相关的结果:
jdk8u_hotspot/src/cpu/x86/vm/assembler_x86.cpp中JVM的c1 compiler / LIR中发出的实际字节数:
用于c1 LIR:src/share/vm/c1/c1_LIRAssembler.cpp
现在我们知道the opcode lir_prefetchr and can search for it或OpenGrok xref和lir_prefetchw,在src/share/vm/c1/c1_LIR.cpp找到 the only example
还有其他地方可以定义预取指令(对于C2,如noted by apangin),the src/cpu/x86/vm/x86_64.ad:
正如JDK-4453409所示,预取是在JDK 1.4中的HotSpot JVM中实现的,以加速GC . 那是超过15年前,没有人会记得为什么它没有在Windows上实现 . 我的猜测是Visual Studio(它一直用于在Windows上构建HotSpot)在这些时候基本上不理解预取指令 . 看起来像是一个改进的地方 .
无论如何,您询问的代码由JVM垃圾收集器在内部使用 . 这不是JIT生成的 . C2 JIT代码生成器规则位于体系结构定义文件x86_64.ad中,并且rules将
PrefetchRead
,PrefetchWrite
和PrefetchAllocation
节点转换为相应的x64指令 .一个有趣的事实是
PrefetchRead
和PrefetchWrite
节点不会在代码中的任何地方创建 . 它们的存在只是为了支持Unsafe.prefetchX内在函数,但它们在JDK 9中是removed .JIT生成预取指令的唯一情况是
PrefetchAllocation
node . 您可以使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
验证PREFETCHNTA
确实是在对象分配后生成的 both on Linux and Windows .java.exe -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly Test