JDK 9 RFR of JDK-8134795: Port fdlibm pow to Java

joe darcy joe.darcy at oracle.com
Wed Sep 16 16:58:15 UTC 2015


Hi Volker,

On 9/16/2015 2:02 AM, Volker Simonis wrote:
> Hi Joe,
>
> nice clean-up! From a maintenance point of view the the old fdlibm has
> been a burden and a constant source of warnings with newer compilers.
>
> What about the final arrays in Pow.compute (BP, DP_H, DP_L). In the
> Interpreter (and even in C2 without EscapeAnalysis) this will lead to
> allocations every time the method is called. Making them static fields
> of 'Pow' will help here. On the other hand, if the arrays are static
> fields of 'Pow', C2 will not be able to directly use the constants but
> will have to load them from the array. So altogether, your current
> implementation is optimal with HotSpot (with EscapeAnalysis turned on
> by default) but might not be the best for other VMs without
> EscapaAnalysis.
>
> Have you done any benchmarking which compares the new Java against the
> old C implementation?
>
>

I don't have exact stats to share, but some quick benchmarks indicate it 
is noticeably faster, more than 10%. The less computation pow does in a 
given case, the faster the Java version should be since the Java -> C -> 
Java cost should roughly be fixed.

Once the code is fully in Java, I would expect further tweaks to refine 
the code. For example, the original FDLIM code used the idiom of pointer 
aliasing a two-element int array with a double. (This idiom was also the 
source of many of those compiler warnings ;-) We can't directly use that 
idiom in Java, but the early versions of the port were a close 
transliteration of the C sources with equivalent Java method calls. That 
still left the code as operating on 32-bit quantities or doing 
comparisons of the double value by looking at its 32 high-order bits. 
Many of those 32-bit operations were removed as the port progressed to 
use clearer (if not also faster) operations such as comparing 64-bit 
double values directly as 64-bit double values.

For example, to my eye I'd much rather read

  185             // Special value of x
  186             if (x_abs == 0.0 ||
  187                 x_abs == INFINITY ||
  188                 x_abs == 1.0) {
  189                 z = x_abs;                 // x is +/-0, +/-inf, +/-1
  190                 if (y < 0.0)
  191                     z = 1.0/z;     // z = (1/|x|)

where x_abs is a double holding the absolute value of x, than the 
original semantically equivalent original

  178     /* special value of x */
  179         if(lx==0) {
  180             if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
  181                 z = ax;                 /*x is +-0,+-inf,+-1*/
  182                 if(hy<0) z = one/z;     /* z = (1/|x|) */

where lx is the lower-order 32 bits of x and ix is the high-order 32 
bits of x with the sign bit zeroed out.

The version sent out for review still has some remaining 32-bit centered 
operations and at least some of those could be eliminated.

Thanks,

-Joe



More information about the core-libs-dev mailing list