根据JLS,我知道strictfp修饰符在方法(和类)上的含义:

JLS 8.4.3.5, strictfp methods:



JLS 15.4 FP-strict expressions:



我一直在努力想出一种方法来获得strictfp方法中的表达式与非strictfp方法中的表达式之间的实际差异。我已经在两台笔记本电脑上进行了尝试,其中一台使用Intel Core i3 CPU,另一台使用Intel Core i7 CPU。而且我没有任何区别。

许多帖子建议不使用strictfp的 native 浮点可能使用80位浮点数,并且在最小的Java double(最接近零)或最高的64位java double之下具有额外的可表示数字。 。

我在下面使用和不使用strictfp修饰符的情况下尝试了这段代码,它给出的结果完全相同。

public static strictfp void withStrictFp() {
    double v = Double.MAX_VALUE;
    System.out.println(v * 1.0000001 / 1.0000001);
    v = Double.MIN_VALUE;
    System.out.println(v / 2 * 2);
}

实际上,我假设只有在将代码编译为程序集时才会显示任何差异,因此我使用-Xcomp JVM参数运行它。但是没什么区别。

我发现another post解释了如何获取HotSpot(OpenJDK documentation)生成的汇编代码。我正在使用java -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly运行我的代码。
具有v * 1.0000001 / 1.0000001修饰符的第一个表达式(strictfp),如果没有,也将被编译为:
  0x000000010f10a0a9: movsd  -0xb1(%rip),%xmm0        # 0x000000010f10a000
                                                ;   {section_word}
  0x000000010f10a0b1: mulsd  -0xb1(%rip),%xmm0        # 0x000000010f10a008
                                                ;   {section_word}
  0x000000010f10a0b9: divsd  -0xb1(%rip),%xmm0        # 0x000000010f10a010
                                                ;   {section_word}

该代码中没有任何东西可以像我期望的那样将每一步的结果截断为64位。 movsdmulsddivsdLooking up the documentation,他们都提到这些(SSE)指令对64位浮点值进行操作,而不是我期望的80位值。因此,这些指令所操作的 double 值集已经是IEEE 754值集,这似乎合乎逻辑,因此拥有strictfp与不拥有strictfp之间不会有任何区别。

我的问题是:
  • 此分析正确吗?我不经常使用英特尔汇编程序,因此我对自己的结论不满意。
  • 是否存在(其他)现代CPU体系结构(具有JVM),对于这些体系结构,使用ojit_code修饰符和不使用ojit_code修饰符时,操作之间会有区别吗?
  • 最佳答案

    如果用“现代”来表示处理器支持您在问题中引用的由编译器生成的SSE2指令(mulsd,...),则答案是否定的,strictfp没什么不同,因为指令集没有作用允许利用strictfp的缺失。可用的指令已经很适合计算strictfp的精确规范。换句话说,在这种现代CPU上,您始终以相同的价格获得strictfp语义。

    如果用“现代”表示历史性的387 FPU,则有可能观察到差异,即中间计算在strictfp模式下会上溢还是下溢(差异在于它可能不会上溢,或者在下溢时保留比预期的)。

    编为387的典型strictfp计算将像 assembly 在this answer,用精心布置乘法通过两个精心挑选的权力,以使下溢行为相同,在IEEE 754 binary64。结果通过64位存储器位置的往返处理可以解决溢出问题。

    在没有strictfp的情况下进行编译的相同计算,每个基本操作将产生一条387条指令,例如,仅针对源级乘法的乘法指令fmulp。 (在程序开始时,将387配置为使用与binary64 53位相同的有效位宽度。)

    10-02 11:28