Remove String.setCharAt().

The internal API String.setCharAt() breaks the assumption
that strings are really immutable. That in turn breaks
string compression invariants - compressible strings must
be compressed. This CL removes the String.setCharAt() API.

The method was used only in String.replace(char, char)
when we found a match, copying the string on first match.
Instead, introduce a new native method that does the whole
replacement with a single call when we find the first match.

StringReplaceBenchmark results on Nexus 6P, lower is better:
  timeReplaceCharNonExistent/EMPTY   41.93 ->   38.25 (-9%)
  timeReplaceCharNonExistent/L_16   114.90 ->   95.09 (-17%)
  timeReplaceCharNonExistent/L_64   419.97 ->  320.65 (-24%)
  timeReplaceCharNonExistent/L_256 1667.01 -> 1091.25 (-35%)
  timeReplaceCharNonExistent/L_512 3253.50 -> 2075.62 (-36%)
  timeReplaceCharRepeated/EMPTY      41.93 ->   39.58 (-6%)
  timeReplaceCharRepeated/L_16      114.87 ->   95.40 (-17%)
  timeReplaceCharRepeated/L_64     1267.29 ->  704.32 (-44%)
  timeReplaceCharRepeated/L_256    5139.14 -> 1361.80 (-74%)
  timeReplaceCharRepeated/L_512   10787.81 -> 2338.41 (-78%)
  timeReplaceSingleChar/EMPTY        41.78 ->   37.16 (-11%)
  timeReplaceSingleChar/L_16        449.54 ->  497.51 (+11%)
  timeReplaceSingleChar/L_64        942.08 ->  891.35 (-5%)
  timeReplaceSingleChar/L_256      2756.18 -> 2174.64 (-21%)
  timeReplaceSingleChar/L_512      5489.91 -> 3983.32 (-27%)

Test: testrunner.py --host
Test: run-libcore-tests.sh --mode=host
Test: testrunner.py --host with string compression enabled.
Test: run-libcore-tests.sh --mode=host with string compression enabled.
Bug: 31040547
Change-Id: I9cf0d5457182f0a33ca8251c29931d3eb624ae07
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 38f6dd4..35ce98e 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -94,7 +94,10 @@
 
   uint16_t CharAt(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void SetCharAt(int32_t index, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_);
+  // Create a new string where all occurences of `old_c` are replaced with `new_c`.
+  // String.doReplace(char, char) is called from String.replace(char, char) when there is a match.
+  ObjPtr<String> DoReplace(Thread* self, uint16_t old_c, uint16_t new_c)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   ObjPtr<String> Intern() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -229,6 +232,14 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
+  static constexpr bool IsASCII(uint16_t c) {
+    // Valid ASCII characters are in range 1..0x7f. Zero is not considered ASCII
+    // because it would complicate the detection of ASCII strings in Modified-UTF8.
+    return (c - 1u) < 0x7fu;
+  }
+
+  static bool AllASCIIExcept(const uint16_t* chars, int32_t length, uint16_t non_ascii);
+
   void SetHashCode(int32_t new_hash_code) REQUIRES_SHARED(Locks::mutator_lock_) {
     // Hash code is invariant so use non-transactional mode. Also disable check as we may run inside
     // a transaction.