Fix supplementary character support.

Fixes all known bugs in our handling of supplementary characters. This change
introduces a performance regression on the assumption that it won't be released
without a corresponding JIT change to enable the code to be inlined back to
pretty much what it used to be.

Bug: 2587122
Change-Id: I3449c9718bbe32ebe53b6c10454ae1dc82105b59
diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h
index 6f67d7e..4f9eeb8 100644
--- a/vm/DalvikVersion.h
+++ b/vm/DalvikVersion.h
@@ -32,6 +32,6 @@
  * way classes load changes, e.g. field ordering or vtable layout.  Changing
  * this guarantees that the optimized form of the DEX file is regenerated.
  */
-#define DALVIK_VM_BUILD         21
+#define DALVIK_VM_BUILD         22
 
 #endif /*_DALVIK_VERSION*/
diff --git a/vm/InlineNative.c b/vm/InlineNative.c
index 22d8fbb..555e956 100644
--- a/vm/InlineNative.c
+++ b/vm/InlineNative.c
@@ -407,8 +407,8 @@
  * Determine the index of the first character matching "ch".  The string
  * to search is described by "chars", "offset", and "count".
  *
- * The "ch" parameter is allowed to be > 0xffff.  Our Java-language
- * implementation does not currently handle this, so neither do we.
+ * The character must be <= 0xffff. Supplementary characters are handled in
+ * Java.
  *
  * The "start" parameter must be clamped to [0..count].
  *
@@ -455,27 +455,13 @@
 }
 
 /*
- * public int indexOf(int c)
- *
- * Scan forward through the string for a matching character.
- */
-static bool javaLangString_indexOf_I(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
-    JValue* pResult)
-{
-    /* null reference check on "this" */
-    if (!dvmValidateObject((Object*) arg0))
-        return false;
-
-    pResult->i = indexOfCommon((Object*) arg0, arg1, 0);
-    return true;
-}
-
-/*
  * public int indexOf(int c, int start)
  *
  * Scan forward through the string for a matching character.
+ * The character must be <= 0xffff; this method does not handle supplementary
+ * characters.
  */
-static bool javaLangString_indexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+static bool javaLangString_fastIndexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
     /* null reference check on "this" */
@@ -666,10 +652,8 @@
         "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
     { javaLangString_equals,
         "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
-    { javaLangString_indexOf_I,
-        "Ljava/lang/String;", "indexOf", "(I)I" },
-    { javaLangString_indexOf_II,
-        "Ljava/lang/String;", "indexOf", "(II)I" },
+    { javaLangString_fastIndexOf_II,
+        "Ljava/lang/String;", "fastIndexOf", "(II)I" },
     { javaLangString_isEmpty,
         "Ljava/lang/String;", "isEmpty", "()Z" },
     { javaLangString_length,
diff --git a/vm/InlineNative.h b/vm/InlineNative.h
index 890226e..9b9ae39 100644
--- a/vm/InlineNative.h
+++ b/vm/InlineNative.h
@@ -54,19 +54,18 @@
     INLINE_STRING_CHARAT = 1,
     INLINE_STRING_COMPARETO = 2,
     INLINE_STRING_EQUALS = 3,
-    INLINE_STRING_INDEXOF_I = 4,
-    INLINE_STRING_INDEXOF_II = 5,
-    INLINE_STRING_IS_EMPTY = 6,
-    INLINE_STRING_LENGTH = 7,
-    INLINE_MATH_ABS_INT = 8,
-    INLINE_MATH_ABS_LONG = 9,
-    INLINE_MATH_ABS_FLOAT = 10,
-    INLINE_MATH_ABS_DOUBLE = 11,
-    INLINE_MATH_MIN_INT = 12,
-    INLINE_MATH_MAX_INT = 13,
-    INLINE_MATH_SQRT = 14,
-    INLINE_MATH_COS = 15,
-    INLINE_MATH_SIN = 16,
+    INLINE_STRING_FASTINDEXOF_II = 4,
+    INLINE_STRING_IS_EMPTY = 5,
+    INLINE_STRING_LENGTH = 6,
+    INLINE_MATH_ABS_INT = 7,
+    INLINE_MATH_ABS_LONG = 8,
+    INLINE_MATH_ABS_FLOAT = 9,
+    INLINE_MATH_ABS_DOUBLE = 10,
+    INLINE_MATH_MIN_INT = 11,
+    INLINE_MATH_MAX_INT = 12,
+    INLINE_MATH_SQRT = 13,
+    INLINE_MATH_COS = 14,
+    INLINE_MATH_SIN = 15,
 } NativeInlineOps;
 
 /*
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 2f157a3..8d63c66 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -2966,7 +2966,7 @@
 #endif
 }
 
-static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
+static bool genInlinedFastIndexOf(CompilationUnit *cUnit, MIR *mir)
 {
 #if defined(USE_GLOBAL_STRING_DEFS)
     return false;
@@ -2976,12 +2976,8 @@
 
     loadValueDirectFixed(cUnit, rlThis, r0);
     loadValueDirectFixed(cUnit, rlChar, r1);
-    if (!singleI) {
-        RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
-        loadValueDirectFixed(cUnit, rlStart, r2);
-    } else {
-        loadConstant(cUnit, r2, 0);
-    }
+    RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
+    loadValueDirectFixed(cUnit, rlStart, r2);
     /* Test objects for NULL */
     genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
     genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
@@ -3144,13 +3140,8 @@
                         return false;
                     else
                         break;
-                case INLINE_STRING_INDEXOF_I:
-                    if (genInlinedIndexOf(cUnit, mir, true /* I */))
-                        return false;
-                    else
-                        break;
-                case INLINE_STRING_INDEXOF_II:
-                    if (genInlinedIndexOf(cUnit, mir, false /* I */))
+                case INLINE_STRING_FASTINDEXOF_II:
+                    if (genInlinedFastIndexOf(cUnit, mir))
                         return false;
                     else
                         break;