Remove JSNI regex literals.

Literal and constructor based Regexp instances have similar
performance characteristics when cached. [1]
I updated most to be cached (if not already) but leave a few
alone where caching doesn't seem worthwhile.

[1] https://jsperf.com/mcmath-regexp-literal-vs-constructor

Change-Id: Icc35d40037a60f021625dc36c914caf87b80eded
Review-Link: https://gwt-review.googlesource.com/#/c/18620/
diff --git a/user/super/com/google/gwt/emul/java/lang/Character.java b/user/super/com/google/gwt/emul/java/lang/Character.java
index 61db5e1..345a629 100644
--- a/user/super/com/google/gwt/emul/java/lang/Character.java
+++ b/user/super/com/google/gwt/emul/java/lang/Character.java
@@ -226,43 +226,46 @@
     return codePoint >= MIN_VALUE && codePoint <= MAX_VALUE;
   }
 
+  private static NativeRegExp digitRegex;
+
   /*
    * TODO: correct Unicode handling.
    */
   public static boolean isDigit(char c) {
-    return digitRegex().test(String.valueOf(c));
+    if (digitRegex == null) {
+      digitRegex = new NativeRegExp("\\d");
+    }
+    return digitRegex.test(String.valueOf(c));
   }
 
-  private static native NativeRegExp digitRegex() /*-{
-    return /\d/;
-  }-*/;
-
   public static boolean isHighSurrogate(char ch) {
     return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE;
   }
 
+  private static NativeRegExp leterRegex;
+
   /*
    * TODO: correct Unicode handling.
    */
   public static boolean isLetter(char c) {
-    return leterRegex().test(String.valueOf(c));
+    if (leterRegex == null) {
+      leterRegex = new NativeRegExp("[A-Z]", "i");
+    }
+    return leterRegex.test(String.valueOf(c));
   }
 
-  private static native NativeRegExp leterRegex() /*-{
-    return /[A-Z]/i;
-  }-*/;
+  private static NativeRegExp isLeterOrDigitRegex;
 
   /*
    * TODO: correct Unicode handling.
    */
   public static boolean isLetterOrDigit(char c) {
-    return leterOrDigitRegex().test(String.valueOf(c));
+    if (isLeterOrDigitRegex == null) {
+      isLeterOrDigitRegex = new NativeRegExp("[A-Z\\d]", "i");
+    }
+    return isLeterOrDigitRegex.test(String.valueOf(c));
   }
 
-  private static native NativeRegExp leterOrDigitRegex() /*-{
-    return /[A-Z\d]/i;
-  }-*/;
-
   /*
    * TODO: correct Unicode handling.
    */
@@ -296,18 +299,27 @@
   }
 
   public static boolean isWhitespace(char ch) {
-    return whitespaceRegex().test(String.valueOf(ch));
+    return isWhitespace(String.valueOf(ch));
   }
 
   public static boolean isWhitespace(int codePoint) {
-    return whitespaceRegex().test(String.fromCodePoint(codePoint));
+    return isWhitespace(String.fromCodePoint(codePoint));
   }
 
-  // The regex would just be /\s/, but browsers handle non-breaking spaces inconsistently. Also,
-  // the Java definition includes separators.
-  private static native NativeRegExp whitespaceRegex() /*-{
-    return /[\t-\r \u1680\u180E\u2000-\u2006\u2008-\u200A\u2028\u2029\u205F\u3000\uFEFF]|[\x1C-\x1F]/;
-  }-*/;
+  private static NativeRegExp whitespaceRegex;
+
+  private static boolean isWhitespace(String ch) {
+    if (whitespaceRegex == null) {
+      // The regex would just be /\s/, but browsers handle non-breaking spaces inconsistently. Also,
+      // the Java definition includes separators.
+      whitespaceRegex =
+          new NativeRegExp(
+              "[\\u1680\\u180E\\u2000-\\u2006\\u2008-\\u200A\\u2028\\u2029\\u205F\\u3000\\uFEFF]"
+                  + "|[\\t-\\r ]"
+                  + "|[\\x1C-\\x1F]");
+    }
+    return whitespaceRegex.test(ch);
+  }
 
   public static boolean isSupplementaryCodePoint(int codePoint) {
     return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT && codePoint <= MAX_CODE_POINT;
diff --git a/user/super/com/google/gwt/emul/java/lang/Number.java b/user/super/com/google/gwt/emul/java/lang/Number.java
index d775032..2e1e955 100644
--- a/user/super/com/google/gwt/emul/java/lang/Number.java
+++ b/user/super/com/google/gwt/emul/java/lang/Number.java
@@ -195,9 +195,8 @@
     return parseFloat(s);
   }
 
-  private static native double parseFloat(String str) /*-{
-    return parseFloat(str);
-  }-*/;
+  @JsMethod(namespace = "<window>")
+  private static native double parseFloat(String str);
 
   /**
    * @skip
@@ -340,15 +339,13 @@
    */
   private static boolean __isValidDouble(String str) {
     if (floatRegex == null) {
-      floatRegex = createFloatRegex();
+      floatRegex =
+          new NativeRegExp(
+              "^\\s*[+-]?(NaN|Infinity|((\\d+\\.?\\d*)|(\\.\\d+))([eE][+-]?\\d+)?[dDfF]?)\\s*$");
     }
     return floatRegex.test(str);
   }
 
-  private static native NativeRegExp createFloatRegex() /*-{
-    return /^\s*[+-]?(NaN|Infinity|((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?[dDfF]?)\s*$/;
-  }-*/;
-
   // CHECKSTYLE_ON
 
   public byte byteValue() {
diff --git a/user/super/com/google/gwt/emul/java/math/BigDecimal.java b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
index 4f734d2..dfb608c 100644
--- a/user/super/com/google/gwt/emul/java/math/BigDecimal.java
+++ b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
@@ -403,16 +403,12 @@
 
   private static boolean isValidBigUnscaledDecimal(String str) {
     if (unscaledRegex == null) {
-      unscaledRegex = createBigDecimalUnscaledRegex();
+      unscaledRegex = new NativeRegExp("^[+-]?\\d*$", "i");
     }
 
     return unscaledRegex.test(str);
   }
 
-  private static native NativeRegExp createBigDecimalUnscaledRegex() /*-{
-    return /^[+-]?\d*$/i;
-  }-*/;
-
   private static double parseUnscaled(String str) {
     return isValidBigUnscaledDecimal(str) ? JsUtils.parseInt(str, 10) : Double.NaN;
   }
diff --git a/user/super/com/google/gwt/emul/java/math/MathContext.java b/user/super/com/google/gwt/emul/java/math/MathContext.java
index 0f5d2a2..4fc5a1f 100644
--- a/user/super/com/google/gwt/emul/java/math/MathContext.java
+++ b/user/super/com/google/gwt/emul/java/math/MathContext.java
@@ -142,7 +142,8 @@
   public MathContext(String val) {
     checkNotNull(val, "null string");
 
-    String[] extractedValues = createParseRegexp().exec(val);
+    String[] extractedValues =
+        new NativeRegExp("^precision=(\\d+)\\ roundingMode=(\\w+)$").exec(val);
     if (extractedValues == null || extractedValues.length != 3) {
       throw new IllegalArgumentException("bad string format");
     }
@@ -159,10 +160,6 @@
     checkCriticalArgument(this.precision >= 0, "Digits < 0");
   }
 
-  private static native NativeRegExp createParseRegexp() /*-{
-    return /^precision=(\d+)\ roundingMode=(\w+)$/;
-  }-*/;
-
   /* Public Methods */
 
   /**
diff --git a/user/super/com/google/gwt/emul/java/nio/charset/Charset.java b/user/super/com/google/gwt/emul/java/nio/charset/Charset.java
index 0025e82..e1af86e 100644
--- a/user/super/com/google/gwt/emul/java/nio/charset/Charset.java
+++ b/user/super/com/google/gwt/emul/java/nio/charset/Charset.java
@@ -57,17 +57,13 @@
       return EmulatedCharset.UTF_8;
     }
 
-    if (!createLegalCharsetNameRegex().test(charsetName)) {
-      throw new IllegalCharsetNameException(charsetName);
-    } else {
+    if (new NativeRegExp("^[A-Za-z0-9][\\w-:\\.\\+]*$").test(charsetName)) {
       throw new UnsupportedCharsetException(charsetName);
+    } else {
+      throw new IllegalCharsetNameException(charsetName);
     }
   }
 
-  private static native NativeRegExp createLegalCharsetNameRegex() /*-{
-    return /^[A-Za-z0-9][\w-:\.\+]*$/;
-  }-*/;
-
   private final String name;
 
   protected Charset(String name, String[] aliasesIgnored) {