An InlineNative for String.isEmpty, so it's not slower than length() == 0.

Before:

       benchmark  ns logarithmic runtime
         IsEmpty  115 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
LengthEqualsZero   21 XXXXX||||||||||||||

With C intrinsic:

          IsEmpty  30 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 LengthEqualsZero  20 XXXXXXXXXXXXXXXXXXXX||||||

With assembler intrinsic:

          IsEmpty  15 XXXXXXXXXXXXXXXXXXXX||||||
 LengthEqualsZero  21 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

(All times on passion.)

Change-Id: Ifcc37fe7b8efdd377675a448e0085e490d6767bc
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index e92eb77..2f157a3 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -2991,8 +2991,11 @@
 #endif
 }
 
-static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+// Generates an inlined String.isEmpty or String.length.
+static bool genInlinedStringIsEmptyOrLength(CompilationUnit *cUnit, MIR *mir,
+                                            bool isEmpty)
 {
+    // dst = src.length();
     RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
     RegLocation rlDest = inlinedTarget(cUnit, mir, false);
     rlObj = loadValue(cUnit, rlObj, kCoreReg);
@@ -3000,10 +3003,26 @@
     genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, NULL);
     loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count,
                  rlResult.lowReg);
+    if (isEmpty) {
+        // dst = (dst == 0);
+        int tReg = dvmCompilerAllocTemp(cUnit);
+        opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg);
+        opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg);
+    }
     storeValue(cUnit, rlDest, rlResult);
     return false;
 }
 
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+{
+    return genInlinedStringIsEmptyOrLength(cUnit, mir, false);
+}
+
+static bool genInlinedStringIsEmpty(CompilationUnit *cUnit, MIR *mir)
+{
+    return genInlinedStringIsEmptyOrLength(cUnit, mir, true);
+}
+
 static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
 {
     int contents = offsetof(ArrayObject, contents);
@@ -3093,6 +3112,8 @@
                     return false;  /* Nop */
                 case INLINE_STRING_LENGTH:
                     return genInlinedStringLength(cUnit, mir);
+                case INLINE_STRING_IS_EMPTY:
+                    return genInlinedStringIsEmpty(cUnit, mir);
                 case INLINE_MATH_ABS_INT:
                     return genInlinedAbsInt(cUnit, mir);
                 case INLINE_MATH_ABS_LONG: