changeset 19813:853f84c7cc6f

fixed Math.pow intrinsic to make a runtime call instead of calling the original method
author Doug Simon <doug.simon@oracle.com>
date Thu, 12 Mar 2015 16:04:37 +0100
parents 97a72dcdac8d
children 4bc9b6838303
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java
diffstat 4 files changed, 36 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Mar 12 16:03:40 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Mar 12 16:04:37 2015 +0100
@@ -1444,6 +1444,7 @@
     @HotSpotVMValue(expression = "SharedRuntime::dsin", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticSinAddress;
     @HotSpotVMValue(expression = "SharedRuntime::dcos", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticCosAddress;
     @HotSpotVMValue(expression = "SharedRuntime::dtan", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticTanAddress;
+    @HotSpotVMValue(expression = "SharedRuntime::dpow", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticPowAddress;
 
     @HotSpotVMValue(expression = "(jint) GraalCounterSize") @Stable public int graalCountersSize;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Mar 12 16:03:40 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Mar 12 16:04:37 2015 +0100
@@ -150,6 +150,7 @@
         registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_POW, c.arithmeticPowAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, ANY_LOCATION);
 
         registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Thu Mar 12 16:03:40 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Thu Mar 12 16:04:37 2015 +0100
@@ -54,7 +54,6 @@
         test("mathSin", value);
         test("mathSqrt", value);
         test("mathTan", value);
-        test("mathPow", value);
         test("mathAll", value);
     }
 
@@ -62,11 +61,26 @@
     public void testMathPow() {
         double a = 34567.891D;
         double b = 4.6D;
-        for (int i = 0; i < 10000; i++) {
-            a = mathPow(a, b);
-            a = StrictMath.pow(a, b);
-        }
         test("mathPow", a, b);
+
+        // Test the values directly handled by the substitution
+
+        // If the second argument is positive or negative zero, then the result is 1.0.
+        test("mathPow", a, 0.0D);
+        test("mathPow", a, -0.0D);
+        // If the second argument is 1.0, then the result is the same as the first argument.
+        test("mathPow", a, 1.0D);
+        // If the second argument is NaN, then the result is NaN.
+        test("mathPow", a, Double.NaN);
+        // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
+        test("mathPow", Double.NaN, b);
+        test("mathPow", Double.NaN, 0.0D);
+        // x**-1 = 1/x
+        test("mathPow", a, -1.0D);
+        // x**2 = x*x
+        test("mathPow", a, 2.0D);
+        // x**0.5 = sqrt(x)
+        test("mathPow", a, 0.5D);
     }
 
     public static double mathPow(double a, double b) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java	Thu Mar 12 16:03:40 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java	Thu Mar 12 16:04:37 2015 +0100
@@ -46,12 +46,12 @@
     @MethodSubstitution(guard = MathGuard.class)
     public static double pow(double x, double y) {
         // If the second argument is positive or negative zero, then the result is 1.0.
-        if (y == 0) {
+        if (y == 0.0D) {
             return 1;
         }
 
         // If the second argument is 1.0, then the result is the same as the first argument.
-        if (y == 1) {
+        if (y == 1.0D) {
             return x;
         }
 
@@ -61,26 +61,25 @@
         }
 
         // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
-        if (Double.isNaN(x) && y != 0) {
+        if (Double.isNaN(x) && y != 0.0D) {
             return Double.NaN;
         }
 
         // x**-1 = 1/x
-        if (y == -1) {
+        if (y == -1.0D) {
             return 1 / x;
         }
 
         // x**2 = x*x
-        if (y == 2) {
+        if (y == 2.0D) {
             return x * x;
         }
 
         // x**0.5 = sqrt(x)
-        if (y == 0.5 && x >= 0) {
+        if (y == 0.5D && x >= 0.0D) {
             return Math.sqrt(x);
         }
-
-        return pow(x, y);
+        return callDouble2(ARITHMETIC_POW, x, y);
     }
 
     // NOTE on snippets below:
@@ -94,7 +93,7 @@
         if (Math.abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.SIN);
         } else {
-            return callDouble(ARITHMETIC_SIN, x);
+            return callDouble1(ARITHMETIC_SIN, x);
         }
     }
 
@@ -103,7 +102,7 @@
         if (Math.abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.COS);
         } else {
-            return callDouble(ARITHMETIC_COS, x);
+            return callDouble1(ARITHMETIC_COS, x);
         }
     }
 
@@ -112,7 +111,7 @@
         if (Math.abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.TAN);
         } else {
-            return callDouble(ARITHMETIC_TAN, x);
+            return callDouble1(ARITHMETIC_TAN, x);
         }
     }
 
@@ -127,7 +126,11 @@
     public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class);
     public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class);
     public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class);
 
     @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
-    public static native double callDouble(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
+    private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
+
+    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b);
 }