< 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 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 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 >