src/share/classes/java/math/BigInteger.java

Print this page
rev 9307 : 8035279: Clean up internal deprecations in BigInteger
Summary: Modify lazily intialized values to use different marker values.
Reviewed-by: TBD

@@ -145,54 +145,45 @@
     // These "redundant fields" are initialized with recognizable nonsense
     // values, and cached the first time they are needed (or never, if they
     // aren't needed).
 
      /**
-     * One plus the bitCount of this BigInteger. Zeros means unitialized.
+     * The bitCount of this BigInteger. {@code Integer.MIN_VALUE} means
+     * uninitialized.
      *
      * @serial
      * @see #bitCount
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int bitCount;
+    private volatile int bitCount = Integer.MIN_VALUE;
 
     /**
-     * One plus the bitLength of this BigInteger. Zeros means unitialized.
-     * (either value is acceptable).
+     * The bitLength of this BigInteger. {@code Integer.MIN_VALUE} means
+     * uninitialized.
      *
      * @serial
      * @see #bitLength()
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int bitLength;
+    private volatile int bitLength = Integer.MIN_VALUE;
 
     /**
-     * Two plus the lowest set bit of this BigInteger, as returned by
-     * getLowestSetBit().
+     * The lowest set bit of this BigInteger, as returned by
+     * getLowestSetBit(). {@code Integer.MIN_VALUE} means uninitialized,
+     * and {@code -1} that this BigInteger contains no one bits.
      *
      * @serial
      * @see #getLowestSetBit
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int lowestSetBit;
+    private volatile int lowestSetBit = Integer.MIN_VALUE;
 
     /**
-     * Two plus the index of the lowest-order int in the magnitude of this
-     * BigInteger that contains a nonzero int, or -2 (either value is acceptable).
+     * The index of the lowest-order int in the magnitude of this
+     * BigInteger that contains a nonzero int, or {@code Integer.MIN_VALUE} to
+     * indicate uninitialized (either value is acceptable).
      * The least significant int has int-number 0, the next int in order of
      * increasing significance has int-number 1, and so forth.
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int firstNonzeroIntNum;
+    private volatile int firstNonzeroIntNum = Integer.MIN_VALUE;
 
     /**
      * This mask is used to obtain the value of an int as if it were unsigned.
      */
     final static long LONG_MASK = 0xffffffffL;

@@ -3238,25 +3229,25 @@
      * (Computes {@code (this == 0? -1 : log2(this & -this))}.)
      *
      * @return index of the rightmost one bit in this BigInteger.
      */
     public int getLowestSetBit() {
-        @SuppressWarnings("deprecation") int lsb = lowestSetBit - 2;
-        if (lsb == -2) {  // lowestSetBit not initialized yet
-            lsb = 0;
+        // This computation has a known, acceptable non-critical race condition.
+        if (lowestSetBit == Integer.MIN_VALUE) {  // lowestSetBit not initialized yet
+            int lsb = 0;
             if (signum == 0) {
                 lsb -= 1;
             } else {
                 // Search for lowest order nonzero int
                 int i,b;
                 for (i=0; (b = getInt(i)) == 0; i++)
                     ;
                 lsb += (i << 5) + Integer.numberOfTrailingZeros(b);
             }
-            lowestSetBit = lsb + 2;
+            lowestSetBit = lsb;
         }
-        return lsb;
+        return lowestSetBit;
     }
 
 
     // Miscellaneous Bit Operations
 

@@ -3269,33 +3260,33 @@
      *
      * @return number of bits in the minimal two's-complement
      *         representation of this BigInteger, <i>excluding</i> a sign bit.
      */
     public int bitLength() {
-        @SuppressWarnings("deprecation") int n = bitLength - 1;
-        if (n == -1) { // bitLength not initialized yet
+        // This computation has a known, acceptable non-critical race condition.
+        if (bitLength == Integer.MIN_VALUE) { // bitLength not initialized yet
             int[] m = mag;
             int len = m.length;
-            if (len == 0) {
-                n = 0; // offset by one to initialize
-            }  else {
+            int n = 0;
+            if (len != 0) {
                 // Calculate the bit length of the magnitude
                 int magBitLength = ((len - 1) << 5) + bitLengthForInt(mag[0]);
                  if (signum < 0) {
                      // Check if magnitude is a power of two
                      boolean pow2 = (Integer.bitCount(mag[0]) == 1);
-                     for (int i=1; i< len && pow2; i++)
+                    for (int i = 1; i < len && pow2; i++) {
                          pow2 = (mag[i] == 0);
+                    }
 
-                     n = (pow2 ? magBitLength -1 : magBitLength);
+                    n = (pow2 ? magBitLength - 1 : magBitLength);
                  } else {
                      n = magBitLength;
                  }
             }
-            bitLength = n + 1;
+            bitLength = n;
         }
-        return n;
+        return bitLength;
     }
 
     /**
      * Returns the number of bits in the two's complement representation
      * of this BigInteger that differ from its sign bit.  This method is

@@ -3303,13 +3294,13 @@
      *
      * @return number of bits in the two's complement representation
      *         of this BigInteger that differ from its sign bit.
      */
     public int bitCount() {
-        @SuppressWarnings("deprecation") int bc = bitCount - 1;
-        if (bc == -1) {  // bitCount not initialized yet
-            bc = 0;      // offset by one to initialize
+        // This computation has a known, acceptable non-critical race condition.
+        if (bitCount == Integer.MIN_VALUE) {  // bitCount not initialized yet
+            int bc = 0;
             // Count the bits in the magnitude
             for (int i=0; i < mag.length; i++)
                 bc += Integer.bitCount(mag[i]);
             if (signum < 0) {
                 // Count the trailing zeros in the magnitude

@@ -3317,13 +3308,13 @@
                 for (j=mag.length-1; mag[j] == 0; j--)
                     magTrailingZeroCount += 32;
                 magTrailingZeroCount += Integer.numberOfTrailingZeros(mag[j]);
                 bc += magTrailingZeroCount - 1;
             }
-            bitCount = bc + 1;
+            bitCount = bc;
         }
-        return bc;
+        return bitCount;
     }
 
     // Primality Testing
 
     /**

@@ -4188,23 +4179,23 @@
      * Returns the index of the int that contains the first nonzero int in the
      * little-endian binary representation of the magnitude (int 0 is the
      * least significant). If the magnitude is zero, return value is undefined.
      */
     private int firstNonzeroIntNum() {
-        int fn = firstNonzeroIntNum - 2;
-        if (fn == -2) { // firstNonzeroIntNum not initialized yet
-            fn = 0;
+        // This computation has a known, acceptable non-critical race condition.
+        if (firstNonzeroIntNum == Integer.MIN_VALUE) { // firstNonzeroIntNum not initialized yet
+            int fn = 0;
 
             // Search for the first nonzero int
             int i;
             int mlen = mag.length;
             for (i = mlen - 1; i >= 0 && mag[i] == 0; i--)
                 ;
             fn = mlen - i - 1;
-            firstNonzeroIntNum = fn + 2; // offset by two to initialize
+            firstNonzeroIntNum = fn;
         }
-        return fn;
+        return firstNonzeroIntNum;
     }
 
     /** use serialVersionUID from JDK 1.1. for interoperability */
     private static final long serialVersionUID = -8287574255936472291L;
 

@@ -4236,15 +4227,14 @@
      * Reconstitute the {@code BigInteger} instance from a stream (that is,
      * deserialize it). The magnitude is read in as an array of bytes
      * for historical reasons, but it is converted to an array of ints
      * and the byte array is discarded.
      * Note:
-     * The current convention is to initialize the cache fields, bitCount,
-     * bitLength and lowestSetBit, to 0 rather than some other marker value.
-     * Therefore, no explicit action to set these fields needs to be taken in
-     * readObject because those fields already have a 0 value be default since
-     * defaultReadObject is not being used.
+     * The current convention is explicitly to initialize the cache fields
+     * bitCount, bitLength, firstNonzeroIntNum, and lowestSetBit to
+     * Integer.MIN_VALUE. This serves to indicate that the actual values need
+     * to be calculated when accessed.
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         /*
          * In order to maintain compatibility with previous serialized forms,

@@ -4286,10 +4276,16 @@
                 checkRange();
             } catch (ArithmeticException e) {
                 throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
             }
         }
+
+        // Initialize cached fields to indicate not computed yet.
+        bitCount = Integer.MIN_VALUE;
+        bitLength = Integer.MIN_VALUE;
+        lowestSetBit = Integer.MIN_VALUE;
+        firstNonzeroIntNum = Integer.MIN_VALUE;
     }
 
     // Support for resetting final fields while deserializing
     private static class UnsafeHolder {
         private static final sun.misc.Unsafe unsafe;