1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.hotspot.test; 26 27 import java.math.BigInteger; 28 import java.util.Random; 29 30 import org.graalvm.compiler.api.test.Graal; 31 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 32 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 33 import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; 34 import org.graalvm.compiler.runtime.RuntimeProvider; 35 36 import org.junit.Test; 37 38 import jdk.vm.ci.amd64.AMD64; 39 import jdk.vm.ci.code.InstalledCode; 40 import jdk.vm.ci.meta.ResolvedJavaMethod; 41 42 /* 43 * Indirectly test intrinsic/call substitutions for (innate) methods: 44 * 45 * BigInteger.implMultiplyToLen 46 * BigInteger.implMulAdd 47 * BigInteger.implMontgomeryMultiply 48 * BigInteger.implMontgomerySquare 49 * BigInteger.implSquareToLen 50 * 51 * via BigInteger.multiply() and .modPow(). Note that the actual substitution 52 * is not tested per se (only execution based on admissible intrinsics). 53 * 54 */ 55 public final class BigIntegerIntrinsicsTest extends MethodSubstitutionTest { 56 57 static final int N = 100; 58 59 @Test 60 public void testMultiplyToLen() throws ClassNotFoundException { 61 62 // Intrinsic must be available. 63 org.junit.Assume.assumeTrue(config.useMultiplyToLenIntrinsic()); 64 // Test case is (currently) AMD64 only. 65 org.junit.Assume.assumeTrue(getTarget().arch instanceof AMD64); 66 67 Class<?> javaclass = Class.forName("java.math.BigInteger"); 68 69 TestIntrinsic tin = new TestIntrinsic("testMultiplyAux", javaclass, 70 "multiply", BigInteger.class); 71 72 for (int i = 0; i < N; i++) { 73 74 BigInteger big1 = randomBig(i); 75 BigInteger big2 = randomBig(i); 76 77 // Invoke BigInteger BigInteger.multiply(BigInteger) 78 BigInteger res1 = (BigInteger) tin.invokeJava(big1, big2); 79 80 // Invoke BigInteger testMultiplyAux(BigInteger) 81 BigInteger res2 = (BigInteger) tin.invokeTest(big1, big2); 82 83 assertDeepEquals(res1, res2); 84 85 // Invoke BigInteger testMultiplyAux(BigInteger) through code handle. 86 BigInteger res3 = (BigInteger) tin.invokeCode(big1, big2); 87 88 assertDeepEquals(res1, res3); 89 } 90 } 91 92 @Test 93 public void testMulAdd() throws ClassNotFoundException { 94 95 // Intrinsic must be available. 96 org.junit.Assume.assumeTrue(config.useMulAddIntrinsic() || 97 config.useSquareToLenIntrinsic()); 98 // Test case is (currently) AMD64 only. 99 org.junit.Assume.assumeTrue(getTarget().arch instanceof AMD64); 100 101 Class<?> javaclass = Class.forName("java.math.BigInteger"); 102 103 TestIntrinsic tin = new TestIntrinsic("testMultiplyAux", javaclass, 104 "multiply", BigInteger.class); 105 106 for (int i = 0; i < N; i++) { 107 108 BigInteger big1 = randomBig(i); 109 110 // Invoke BigInteger BigInteger.multiply(BigInteger) 111 BigInteger res1 = (BigInteger) tin.invokeJava(big1, big1); 112 113 // Invoke BigInteger testMultiplyAux(BigInteger) 114 BigInteger res2 = (BigInteger) tin.invokeTest(big1, big1); 115 116 assertDeepEquals(res1, res2); 117 118 // Invoke BigInteger testMultiplyAux(BigInteger) through code handle. 119 BigInteger res3 = (BigInteger) tin.invokeCode(big1, big1); 120 121 assertDeepEquals(res1, res3); 122 } 123 } 124 125 @Test 126 public void testMontgomery() throws ClassNotFoundException { 127 128 // Intrinsic must be available. 129 org.junit.Assume.assumeTrue(config.useMontgomeryMultiplyIntrinsic() || 130 config.useMontgomerySquareIntrinsic()); 131 // Test case is (currently) AMD64 only. 132 org.junit.Assume.assumeTrue(getTarget().arch instanceof AMD64); 133 134 Class<?> javaclass = Class.forName("java.math.BigInteger"); 135 136 TestIntrinsic tin = new TestIntrinsic("testMontgomeryAux", javaclass, 137 "modPow", BigInteger.class, BigInteger.class); 138 139 for (int i = 0; i < N; i++) { 140 141 BigInteger big1 = randomBig(i); 142 BigInteger big2 = randomBig(i); 143 144 // Invoke BigInteger BigInteger.modPow(BigExp, BigInteger) 145 BigInteger res1 = (BigInteger) tin.invokeJava(big1, bigTwo, big2); 146 147 // Invoke BigInteger testMontgomeryAux(BigInteger, BigExp, BigInteger) 148 BigInteger res2 = (BigInteger) tin.invokeTest(big1, bigTwo, big2); 149 150 assertDeepEquals(res1, res2); 151 152 // Invoke BigInteger testMontgomeryAux(BigInteger, BigExp, BigInteger) through code 153 // handle. 154 BigInteger res3 = (BigInteger) tin.invokeCode(big1, bigTwo, big2); 155 156 assertDeepEquals(res1, res3); 157 } 158 } 159 160 public static BigInteger testMultiplyAux(BigInteger a, BigInteger b) { 161 return a.multiply(b); 162 } 163 164 public static BigInteger testMontgomeryAux(BigInteger a, BigInteger exp, BigInteger b) { 165 return a.modPow(exp, b); 166 } 167 168 private class TestIntrinsic { 169 170 TestIntrinsic(String testmname, Class<?> javaclass, String javamname, Class<?>... params) { 171 172 javamethod = getResolvedJavaMethod(javaclass, javamname, params); 173 testmethod = getResolvedJavaMethod(testmname); 174 175 assert javamethod != null; 176 assert testmethod != null; 177 178 // Force the test method to be compiled. 179 testcode = getCode(testmethod); 180 181 assert testcode != null; 182 } 183 184 Object invokeJava(BigInteger big, Object... args) { 185 186 return invokeSafe(javamethod, big, args); 187 } 188 189 Object invokeTest(Object... args) { 190 191 return invokeSafe(testmethod, null, args); 192 } 193 194 Object invokeCode(Object... args) { 195 196 return executeVarargsSafe(testcode, args); 197 } 198 199 // Private data section: 200 private ResolvedJavaMethod javamethod; 201 private ResolvedJavaMethod testmethod; 202 private InstalledCode testcode; 203 } 204 205 private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig(); 206 207 private static BigInteger bigTwo = BigInteger.valueOf(2); 208 private static Random rnd = new Random(17); 209 210 private static BigInteger randomBig(int i) { 211 return new BigInteger(rnd.nextInt(4096) + i2sz(i), rnd); 212 } 213 214 private static int i2sz(int i) { 215 return i * 3 + 1; 216 } 217 }