I did a deep dive a while back into the floating-point semantics of many languages, included JIT'd languages, which mostly uncovers that very few languages are particularly precise in their specification.
The tl;dr for the relevant languages here is:
* Java requires full IEEE 754 conformance (and bounds ULPs on java.lang.Math functions, although not fully correctly-rounded), although (now removed) strictfp permitted a slightly more relaxed mode to make it easier to implement using x87 FPU arithmetic.
* C# has license for excess precision mode and denormal flushing.
* JS is strict IEEE 754 conformance, except for math library functions (which can be more approximate).
* Go permits FMA contraction (but is otherwise silent).
* Most other interpreted/JIT'd languages pretty much go "you get your machine floating-point."
And, FWIW, all of those floating-point semantics are orthogonal to things enabled by -ffast-math or similar flags! The only languages that really discuss such things are C (in a TS nobody implements), Fortran (which lets you rearrange expressions as long as you preserve parentheses), Julia (which has a fast_fma-like function and a fast-math macro), and now Rust.