rgh*_*ome 6 java native intrinsics
Java固有函数在很多地方都提到过(例如here)。我的理解是,这些是使用特殊本机代码处理的方法。这似乎类似于JNI方法,它也是本机代码块。
有什么不同?
主要区别在于,JVM 知道内在方法的实现,并且可以使用依赖于机器的,经过优化的指令(有时甚至使用单个处理器指令)来代替原始的Java代码,而JNI方法的实现是未知的一个JVM。
后者施加了一些限制,例如无法对JNI方法应用某些优化技术,需要在调用堆栈上做额外的工作等。
PS您提供的链接包含该特定JVM的已知方法的列表。此列表可能因一个JVM而异。
JIT知道内在函数,因此可以将相关的机器指令内联到它的JITing代码中,并作为热循环的一部分对其进行优化。
JNI函数对于编译器来说是100%的黑匣子,具有相当大的调用/返回开销(尤其是如果仅将其用于标量的话)。
但是,即使只是int bitcount(unsigned x){ return __builtin_popcount(x); }对编译为x86-64 的函数的调用popcnt eax, edi;ret(x86-64 System V调用约定)(JIT编译器发出的调用者)仍必须假定所有被调用阻塞的寄存器都被破坏了。在x86-64上,这是大多数整数寄存器和所有FP /向量寄存器。(就像调用黑盒函数与内部函数的提前C ++编译器的成本一样)。但是我怀疑调用JNI函数的成本还包括一些额外的开销。
当然,对任何未知函数的调用都意味着,如果JIT编译器无法证明没有其他东西可以引用它们,那么寄存器中的变量可能需要同步到内存。(转义分析。)
另外,内在函数意味着JVM可以了解函数的功能,并可以通过该函数进行优化。例如,在持续传播的情况下,它知道popcount(5)= 2个设置位。但是对于实际的JNI函数,它仍然必须调用它。除非有某种方法将该函数声明为“ pure”,以便CSE进行,否则每个调用都是明显的副作用。
使用大量内联,编译时间常数并不罕见。
“本机”方法是一个广义术语,表示该方法在JVM本身或动态加载的本机库中实现。
甲native方法是声明为方法native在类的Java源代码。
“固有”方法是JVM运行时(特别是JIT编译器)对其执行特殊优化的方法。“固有的”含义之一就是调用序列不是JNI调用。但是优化可能会更广泛。
请注意,native和“ intrisic”是正交的:
native“本征的”,也可以是“本征的”。例如arraycopy。同时native“本征”和“固有”的方法将不会实现为JNI方法。native;例如某些StringJava版本中的某些方法。在这种情况下,该方法的JIT编译版本将忽略Java源代码及其字节代码。这似乎类似于JNI方法,它也是本机代码块。
JNI是用于实现native非“内部”方法的API 。因此,JNI方法是在C / C ++中实现的方法,其签名与JNI调用序列兼容。
问题在于,JNI方法调用序列比典型的Java到Java或Java到内部调用序列更重。(这是由于JNI调用的通用性质,以及需要在Java对应的C / C ++类型之间检查并映射参数/结果……之类的东西。)
与Java和内在方法相比,JNI方法的另一个问题是JIT编译器对前者的工作了解为零,因此无法跨调用边界应用各种优化。例如内联。
| 归档时间: |
|
| 查看次数: |
337 次 |
| 最近记录: |