< prev index next >

src/java.base/share/classes/java/lang/Integer.java

Print this page

        

*** 394,404 **** StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]); val >>>= shift; } while (charPos > offset); } ! static final char [] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', --- 394,404 ---- StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]); val >>>= shift; } while (charPos > offset); } ! static final byte[] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
*** 407,417 **** '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', } ; ! static final char [] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', --- 407,417 ---- '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', } ; ! static final byte[] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
*** 420,444 **** '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', } ; - // I use the "invariant division by multiplication" trick to - // accelerate Integer.toString. In particular we want to - // avoid division by 10. - // - // The "trick" has roughly the same performance characteristics - // as the "classic" Integer.toString code on a non-JIT VM. - // The trick avoids .rem and .div calls but has a longer code - // path and is thus dominated by dispatch overhead. In the - // JIT case the dispatch overhead doesn't exist and the - // "trick" is considerably faster than the classic code. - // - // RE: Division by Invariant Integers using Multiplication - // T Gralund, P Montgomery - // ACM PLDI 1994 - // /** * Returns a {@code String} object representing the * specified integer. The argument is converted to signed decimal * representation and returned as a string, exactly as if the --- 420,429 ----
*** 448,460 **** * @param i an integer to be converted. * @return a string representation of the argument in base&nbsp;10. */ @HotSpotIntrinsicCandidate public static String toString(int i) { ! if (i == Integer.MIN_VALUE) ! return "-2147483648"; ! int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; getChars(i, size, buf); return new String(buf, LATIN1); } else { --- 433,443 ---- * @param i an integer to be converted. * @return a string representation of the argument in base&nbsp;10. */ @HotSpotIntrinsicCandidate public static String toString(int i) { ! int size = stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; getChars(i, size, buf); return new String(buf, LATIN1); } else {
*** 487,574 **** * character array buf. The characters are placed into * the buffer backwards starting with the least significant * digit at the specified index (exclusive), and working * backwards from there. * ! * Will fail if i == Integer.MIN_VALUE */ static void getChars(int i, int index, byte[] buf) { int q, r; int charPos = index; - char sign = 0; ! if (i < 0) { ! sign = '-'; i = -i; } // Generate two digits per iteration ! while (i >= 65536) { q = i / 100; ! // really: r = i - (q * 100); ! r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; ! buf [--charPos] = (byte)DigitOnes[r]; ! buf [--charPos] = (byte)DigitTens[r]; } ! // Fall thru to fast mode for smaller numbers ! // assert(i <= 65536, i); ! for (;;) { ! q = (i * 52429) >>> (16+3); ! r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... ! buf [--charPos] = (byte)digits [r]; ! i = q; ! if (i == 0) break; } ! if (sign != 0) { ! buf [--charPos] = (byte)sign; } } static void getCharsUTF16(int i, int index, byte[] buf) { int q, r; int charPos = index; - char sign = 0; ! if (i < 0) { ! sign = '-'; i = -i; } ! // Generate two digits per iteration ! while (i >= 65536) { q = i / 100; ! // really: r = i - (q * 100); ! r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; StringUTF16.putChar(buf, --charPos, DigitOnes[r]); StringUTF16.putChar(buf, --charPos, DigitTens[r]); } ! // Fall thru to fast mode for smaller numbers ! // assert(i <= 65536, i); ! for (;;) { ! q = (i * 52429) >>> (16+3); ! r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... ! StringUTF16.putChar(buf, --charPos, Integer.digits[r]); ! i = q; ! if (i == 0) break; } ! if (sign != 0) { ! StringUTF16.putChar(buf, --charPos, sign); } } ! static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, ! 99999999, 999999999, Integer.MAX_VALUE }; ! ! // Requires positive x static int stringSize(int x) { ! for (int i=0; ; i++) ! if (x <= sizeTable[i]) ! return i+1; } /** * Parses the string argument as a signed integer in the radix * specified by the second argument. The characters in the string --- 470,574 ---- * character array buf. The characters are placed into * the buffer backwards starting with the least significant * digit at the specified index (exclusive), and working * backwards from there. * ! * @implNote This method converts positive inputs into negative ! * values, to cover the Integer.MIN_VALUE case. Converting otherwise ! * (negative to positive) will expose -Integer.MIN_VALUE that overflows ! * integer. */ static void getChars(int i, int index, byte[] buf) { int q, r; int charPos = index; ! boolean negative = i < 0; ! if (!negative) { i = -i; } // Generate two digits per iteration ! while (i <= -100) { q = i / 100; ! r = (q * 100) - i; i = q; ! buf[--charPos] = DigitOnes[r]; ! buf[--charPos] = DigitTens[r]; } ! // We know there are at most two digits left at this point. ! q = i / 10; ! r = (q * 10) - i; ! buf[--charPos] = (byte)('0' + r); ! ! // Whatever left is the remaining digit. ! if (q < 0) { ! buf[--charPos] = (byte)('0' - q); } ! ! if (negative) { ! buf[--charPos] = (byte)'-'; } } static void getCharsUTF16(int i, int index, byte[] buf) { int q, r; int charPos = index; ! boolean negative = (i < 0); ! if (!negative) { i = -i; } ! // Get 2 digits/iteration using ints ! while (i <= -100) { q = i / 100; ! r = (q * 100) - i; i = q; StringUTF16.putChar(buf, --charPos, DigitOnes[r]); StringUTF16.putChar(buf, --charPos, DigitTens[r]); } ! // We know there are at most two digits left at this point. ! q = i / 10; ! r = (q * 10) - i; ! StringUTF16.putChar(buf, --charPos, '0' + r); ! ! // Whatever left is the remaining digit. ! if (q < 0) { ! StringUTF16.putChar(buf, --charPos, '0' - q); } ! ! if (negative) { ! StringUTF16.putChar(buf, --charPos, '-'); } } ! /** ! * Returns the string representation size for a given int value. ! * ! * @param x int value ! * @return string size ! * ! * @implNote There are other ways to compute this: e.g. binary search, ! * but values are biased heavily towards zero, and therefore linear search ! * wins. The iteration results are also routinely inlined in the generated ! * code after loop unrolling. ! */ static int stringSize(int x) { ! int d = 1; ! if (x >= 0) { ! d = 0; ! x = -x; ! } ! int p = -10; ! for (int i = 1; i < 10; i++) { ! if (x > p) ! return i + d; ! p = 10 * p; ! } ! return 10 + d; } /** * Parses the string argument as a signed integer in the radix * specified by the second argument. The characters in the string
< prev index next >