8196331: Optimize Character.digit for latin1 input
authorredestad
Tue, 30 Jan 2018 18:57:49 +0100
changeset 48684 29c1fede33a6
parent 48683 b2f2bdba0472
child 48685 f13f9b941bc7
8196331: Optimize Character.digit for latin1 input Reviewed-by: psandoz, martin, sherman
make/data/characterdata/CharacterDataLatin1.java.template
--- a/make/data/characterdata/CharacterDataLatin1.java.template	Fri Jan 26 11:27:53 2018 -0800
+++ b/make/data/characterdata/CharacterDataLatin1.java.template	Tue Jan 30 18:57:49 2018 +0100
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import java.util.Arrays;
+
 /** The CharacterData class encapsulates the large tables found in
     Java.lang.Character. */
 
@@ -159,20 +161,39 @@
         return toUpperCase(ch);
     }
 
+    // Digit values for codePoints in the 0-255 range. Contents generated using:
+    // for (char i = 0; i < 256; i++) {
+    //     int v = -1;
+    //     if (i >= '0' && i <= '9') { v = i - '0'; } 
+    //     else if (i >= 'A' && i <= 'Z') { v = i - 'A' + 10; }
+    //     else if (i >= 'a' && i <= 'z') { v = i - 'a' + 10; }
+    //     if (i % 20 == 0) System.out.println();
+    //     System.out.printf("%2d, ", v);
+    // }
+    //
+    // Analysis has shown that generating the whole array allows the JIT to generate
+    // better code compared to a slimmed down array, such as one cutting off after 'z'
+    private static final byte[] DIGITS = new byte[] {
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1,
+        -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, 10, 11, 12,
+        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+        33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+
     int digit(int ch, int radix) {
-        int value = -1;
-        if (radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX) {
-            int val = getProperties(ch);
-            int kind = val & $$maskType;
-            if (kind == Character.DECIMAL_DIGIT_NUMBER) {
-                value = ch + ((val & $$maskDigitOffset) >> $$shiftDigitOffset) & $$maskDigit;
-            }
-            else if ((val & $$maskNumericType) == $$valueJavaSupradecimal) {
-                // Java supradecimal digit
-                value = (ch + ((val & $$maskDigitOffset) >> $$shiftDigitOffset) & $$maskDigit) + 10;
-            }
+        int value = DIGITS[ch];
+        if (value >= 0 && radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX) {
+            value = (value < radix) ? value : -1;
         }
-        return (value < radix) ? value : -1;
+        return value;
     }
 
     int getNumericValue(int ch) {