|
2 | 2 |
|
3 | 3 | import org.jetbrains.annotations.NotNull;
|
4 | 4 |
|
| 5 | +import java.lang.invoke.MethodHandle; |
| 6 | +import java.lang.invoke.MethodHandles; |
| 7 | +import java.lang.reflect.Method; |
| 8 | + |
5 | 9 | class Maths {
|
6 | 10 | @NotNull
|
7 | 11 | private static final Maths INSTANCE;
|
8 | 12 |
|
9 | 13 | static {
|
10 |
| - boolean hasMultiplyHigh = true; |
| 14 | + Maths maths = null; |
11 | 15 | try {
|
12 |
| - Math.multiplyHigh(0, 0); |
| 16 | + Method multiplyHigh = Math.class.getDeclaredMethod("multiplyHigh", int.class, int.class); |
| 17 | + MethodHandle multiplyHighMH = MethodHandles.lookup().unreflect(multiplyHigh); |
| 18 | + maths = new MathsJDK9(multiplyHighMH); |
13 | 19 | } catch (final Throwable ignore) {
|
14 |
| - hasMultiplyHigh = false; |
| 20 | + maths = new Maths(); |
15 | 21 | }
|
16 |
| - INSTANCE = hasMultiplyHigh ? new MathsJDK9() : new Maths(); |
| 22 | + INSTANCE = maths; |
17 | 23 | }
|
18 | 24 |
|
19 | 25 | public static long unsignedLongMulXorFold(final long lhs, final long rhs) {
|
@@ -62,16 +68,30 @@ long unsignedLongMulHighImp(final long lhs, final long rhs) {
|
62 | 68 | }
|
63 | 69 |
|
64 | 70 | class MathsJDK9 extends Maths {
|
| 71 | + private final MethodHandle multiplyHighMH; |
| 72 | + |
| 73 | + public MathsJDK9(MethodHandle multiplyHighMH) { |
| 74 | + this.multiplyHighMH = multiplyHighMH; |
| 75 | + } |
| 76 | + |
65 | 77 | // Math.multiplyHigh() is intrinsified from JDK 10. But JDK 9 is out of life, we always prefer
|
66 | 78 | // this version to the scalar one.
|
67 | 79 | @Override
|
68 | 80 | long unsignedLongMulXorFoldImp(final long lhs, final long rhs) {
|
69 |
| - final long upper = Math.multiplyHigh(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs); |
| 81 | + final long upper = invokeExact(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs); |
70 | 82 | final long lower = lhs * rhs;
|
71 | 83 | return lower ^ upper;
|
72 | 84 | }
|
73 | 85 | @Override
|
74 | 86 | long unsignedLongMulHighImp(final long lhs, final long rhs) {
|
75 |
| - return Math.multiplyHigh(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs); |
| 87 | + return invokeExact(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs); |
| 88 | + } |
| 89 | + |
| 90 | + private long invokeExact(long lhs, long rhs) { |
| 91 | + try { |
| 92 | + return (long) multiplyHighMH.invokeExact(lhs, rhs); |
| 93 | + } catch (Throwable e) { |
| 94 | + throw new AssertionError(e); |
| 95 | + } |
76 | 96 | }
|
77 | 97 | }
|
0 commit comments