Es sieht für mich aus einem sehr trivialen Testfall, wie die JVM Round-Trips jede double
Berechnung durch Speicher, um die Rundung zu bekommen, die es will. Es scheint auch etwas seltsam mit ein paar magischen Konstanten zu tun. Hier ist, was sie für mich getan hat für eine einfache „Compute 2^n naiv“ Programm:
0xb1e444b0: fld1
0xb1e444b2: jmp 0xb1e444dd ;*iload
; - fptest::[email protected] (line 6)
0xb1e444b7: nop
0xb1e444b8: fldt 0xb523a2c8 ; {external_word}
0xb1e444be: fmulp %st,%st(1)
0xb1e444c0: fmull 0xb1e44490 ; {section_word}
0xb1e444c6: fldt 0xb523a2bc ; {external_word}
0xb1e444cc: fmulp %st,%st(1)
0xb1e444ce: fstpl 0x10(%esp)
0xb1e444d2: inc %esi ; OopMap{off=51}
;*goto
; - fptest::[email protected] (line 6)
0xb1e444d3: test %eax,0xb3f8d100 ; {poll}
0xb1e444d9: fldl 0x10(%esp) ;*goto
; - fptest::[email protected] (line 6)
0xb1e444dd: cmp %ecx,%esi
0xb1e444df: jl 0xb1e444b8 ;*if_icmpge
; - fptest::[email protected] (line 6)
Ich glaube 0xb523a2c8
und 0xb523a2bc
sind _fpu_subnormal_bias1
und _fpu_subnormal_bias2
vom Hotspot-Quellcode. _fpu_subnormal_bias1
sieht aus wie 0x03ff8000000000000000
und _fpu_subnormal_bias2
scheint 0x7bff8000000000000000
zu sein. _fpu_subnormal_bias1
hat die Wirkung der Skalierung der kleinsten Normalen double
auf die kleinste Normale long double
; Wenn die FPU auf 53 Bits aufrundet, wird das "Richtige" passieren.
Ich würde spekulieren, dass die scheinbar sinnlose Anweisung test
da ist, so dass der Thread unterbrochen werden kann, indem diese Seite für den Fall, dass ein GC erforderlich ist, nicht lesbar ist.
Hier ist der Java-Code:
import java.io.*;
public strictfp class fptest {
public static double calc(int k) {
double a = 2.0;
double b = 1.0;
for (int i = 0; i < k; i++) {
b *= a;
}
return b;
}
public static double intest() {
double d = 0;
for (int i = 0; i < 4100; i++) d += calc(i);
return d;
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++)
System.out.println(intest());
}
}
weiter Graben, der Code für diese Operationen ist in plain sight im Code OpenJDK in hotspot/src/cpu/x86/vm/x86_63.ad
. Relevante Schnipsel:
instruct strictfp_mulD_reg(regDPR1 dst, regnotDPR1 src) %{
predicate(UseSSE<=1 && Compile::current()->has_method() && Compile::current()
->method()->is_strict());
match(Set dst (MulD dst src));
ins_cost(1); // Select this instruction for all strict FP double multiplies
format %{ "FLD StubRoutines::_fpu_subnormal_bias1\n\t"
"DMULp $dst,ST\n\t"
"FLD $src\n\t"
"DMULp $dst,ST\n\t"
"FLD StubRoutines::_fpu_subnormal_bias2\n\t"
"DMULp $dst,ST\n\t" %}
opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
ins_encode(strictfp_bias1(dst),
Push_Reg_D(src),
OpcP, RegOpc(dst),
strictfp_bias2(dst));
ins_pipe(fpu_reg_reg);
%}
instruct strictfp_divD_reg(regDPR1 dst, regnotDPR1 src) %{
predicate (UseSSE<=1);
match(Set dst (DivD dst src));
predicate(UseSSE<=1 && Compile::current()->has_method() && Compile::current()
->method()->is_strict());
ins_cost(01);
format %{ "FLD StubRoutines::_fpu_subnormal_bias1\n\t"
"DMULp $dst,ST\n\t"
"FLD $src\n\t"
"FDIVp $dst,ST\n\t"
"FLD StubRoutines::_fpu_subnormal_bias2\n\t"
"DMULp $dst,ST\n\t" %}
opcode(0xDE, 0x7); /* DE F8+i or DE /7*/
ins_encode(strictfp_bias1(dst),
Push_Reg_D(src),
OpcP, RegOpc(dst),
strictfp_bias2(dst));
ins_pipe(fpu_reg_reg);
%}
Ich sehe nichts für Addition und Subtraktion, aber ich wette, sie nur ein Add/subtrahieren mit der FPU in 53-Bit-Modus und dann Round-Trip das Ergebnis durch die Erinnerung. Ich bin ein bisschen neugierig, ob es einen trickreichen Überlauf gibt, bei dem sie falsch liegen, aber ich bin nicht neugierig genug, um das herauszufinden.
@ ChrisJester-Young Danke, dass du geholfen hast, die Frage klarer zu stellen. –
Ich kenne die Antwort auf Ihre Frage nicht. Wenn Sie jedoch über einen solchen Computer verfügen, können Sie die Flags "-XX: + UnlockDiagnosticVMOptions -XX: + PrintAssembly" übergeben, um zu sehen, welcher Code generiert wird. – tmyklebu
@tmyklebu Ich weiß nicht einmal, ob ich eine Java-Runtime installiert habe.Ich habe nur ein perverses Interesse an der Nachahmung der Doppelpräzision mit dem 387. Auch jemand hat mir einmal einen Verweis auf die Memoiren eines Doktoranden zu genau diesem Thema gegeben, die ich vergessen habe zu archivieren und nun nicht mehr finden kann. Du warst es nicht, oder? –