diff --git a/jdk/src/share/classes/java/math/BigInteger.java b/jdk/src/share/classes/java/math/BigInteger.java index 48354a9559c..6569fcb1796 100644 --- a/jdk/src/share/classes/java/math/BigInteger.java +++ b/jdk/src/share/classes/java/math/BigInteger.java @@ -1042,7 +1042,7 @@ public class BigInteger extends Number implements Comparable { * recalculate powers of radix^(2^n) more than once. This speeds * Schoenhage recursive base conversion significantly. */ - private static ArrayList[] powerCache; + private static volatile BigInteger[][] powerCache; /** The cache of logarithms of radices for base conversion. */ private static final double[] logCache; @@ -1063,14 +1063,12 @@ public class BigInteger extends Number implements Comparable { * with just the very first value. Additional values will be created * on demand. */ - powerCache = (ArrayList[]) - new ArrayList[Character.MAX_RADIX+1]; + powerCache = new BigInteger[Character.MAX_RADIX+1][]; logCache = new double[Character.MAX_RADIX+1]; for (int i=Character.MIN_RADIX; i<=Character.MAX_RADIX; i++) { - powerCache[i] = new ArrayList(1); - powerCache[i].add(BigInteger.valueOf(i)); + powerCache[i] = new BigInteger[] { BigInteger.valueOf(i) }; logCache[i] = Math.log(i); } } @@ -3454,22 +3452,25 @@ public class BigInteger extends Number implements Comparable { * This could be changed to a more complicated caching method using * Future. */ - private static synchronized BigInteger getRadixConversionCache(int radix, - int exponent) { - BigInteger retVal = null; - ArrayList cacheLine = powerCache[radix]; - int oldSize = cacheLine.size(); - if (exponent >= oldSize) { - cacheLine.ensureCapacity(exponent+1); - for (int i=oldSize; i<=exponent; i++) { - retVal = cacheLine.get(i-1).square(); - cacheLine.add(i, retVal); - } + private static BigInteger getRadixConversionCache(int radix, int exponent) { + BigInteger[] cacheLine = powerCache[radix]; // volatile read + if (exponent < cacheLine.length) { + return cacheLine[exponent]; } - else - retVal = cacheLine.get(exponent); - return retVal; + int oldLength = cacheLine.length; + cacheLine = Arrays.copyOf(cacheLine, exponent + 1); + for (int i = oldLength; i <= exponent; i++) { + cacheLine[i] = cacheLine[i - 1].pow(2); + } + + BigInteger[][] pc = powerCache; // volatile read again + if (exponent >= pc[radix].length) { + pc = pc.clone(); + pc[radix] = cacheLine; + powerCache = pc; // volatile write, publish + } + return cacheLine[exponent]; } /* zero[i] is a string of i consecutive zeros. */