OSDN Git Service

Jit - optimized inline string compareto, indexof; fill_array_data bug fix
authorBill Buzbee <buzbee@google.com>
Mon, 2 Nov 2009 17:23:49 +0000 (09:23 -0800)
committerBill Buzbee <buzbee@google.com>
Mon, 2 Nov 2009 19:05:53 +0000 (11:05 -0800)
Added flushAllRegs() prior to C handlers in preparation for upcoming support
for holding live/dirty values in physical registers.

12 files changed:
vm/compiler/codegen/arm/Codegen.c
vm/compiler/template/armv5te-vfp/TemplateOpList.h
vm/compiler/template/armv5te/TEMPLATE_STRING_COMPARETO.S [new file with mode: 0644]
vm/compiler/template/armv5te/TEMPLATE_STRING_INDEXOF.S [new file with mode: 0644]
vm/compiler/template/armv5te/TemplateOpList.h
vm/compiler/template/armv7-a/TemplateOpList.h
vm/compiler/template/config-armv5te-vfp
vm/compiler/template/config-armv7-a
vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
vm/mterp/common/asm-constants.h

index 9563df1..8631580 100644 (file)
@@ -1440,6 +1440,7 @@ bool handleArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
         default:
             return true;
     }
+    flushAllRegs(cUnit);   /* Send everything to home location */
     loadValueDirectFixed(cUnit, rlSrc1, r0);
     loadValueDirectFixed(cUnit, rlSrc2, r1);
     loadConstant(cUnit, r2, (int)funct);
@@ -1492,6 +1493,7 @@ bool handleArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir,
         default:
             return true;
     }
+    flushAllRegs(cUnit);   /* Send everything to home location */
     loadConstant(cUnit, rlr, (int)funct);
     loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
     loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
@@ -1584,6 +1586,7 @@ static bool handleArithOpLong(CompilationUnit *cUnit, MIR *mir,
         genLong3Addr(cUnit, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
     } else {
         // Adjust return regs in to handle case of rem returning r2/r3
+        flushAllRegs(cUnit);   /* Send everything to home location */
         loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
         loadConstant(cUnit, rlr, (int) callTgt);
         loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
@@ -1694,6 +1697,7 @@ static bool handleArithOpInt(CompilationUnit *cUnit, MIR *mir,
         storeValue(cUnit, rlDest, rlResult);
     } else {
         RegLocation rlResult;
+        flushAllRegs(cUnit);   /* Send everything to home location */
         loadValueDirectFixed(cUnit, rlSrc2, r1);
         loadConstant(cUnit, r2, (int) callTgt);
         loadValueDirectFixed(cUnit, rlSrc1, r0);
@@ -1828,6 +1832,7 @@ static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
      */
     RegLocation rlSrc;
     RegLocation rlDest;
+    flushAllRegs(cUnit);   /* Send everything to home location */
     if (srcSize == 1) {
         rlSrc = getSrcLoc(cUnit, mir, 0);
         loadValueDirectFixed(cUnit, rlSrc, r0);
@@ -2240,6 +2245,7 @@ static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
 
 static void handleMonitorPortable(CompilationUnit *cUnit, MIR *mir)
 {
+    flushAllRegs(cUnit);   /* Send everything to home location */
     genExportPC(cUnit, mir);
     RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
     loadValueDirectFixed(cUnit, rlSrc, r1);
@@ -2513,6 +2519,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
              * with.  However, Alloc might throw, so we need to genExportPC()
              */
             assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
+            flushAllRegs(cUnit);   /* Send everything to home location */
             genExportPC(cUnit, mir);
             loadConstant(cUnit, r2, (int)dvmAllocObject);
             loadConstant(cUnit, r0, (int) classPtr);
@@ -2545,6 +2552,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
              */
             ClassObject *classPtr =
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
+            flushAllRegs(cUnit);   /* Send everything to home location */
             loadConstant(cUnit, r1, (int) classPtr );
             rlSrc = getSrcLoc(cUnit, mir, 0);
             rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
@@ -2925,6 +2933,7 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
                 genInterpSingleStep(cUnit, mir);
                 return false;
             }
+            flushAllRegs(cUnit);   /* Send everything to home location */
             loadValueDirectFixed(cUnit, rlSrc, r0);
             clobberReg(cUnit, r0);
             if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
@@ -2984,6 +2993,7 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
             void *classPtr = (void*)
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
             assert(classPtr != NULL);
+            flushAllRegs(cUnit);   /* Send everything to home location */
             genExportPC(cUnit, mir);
             loadValueDirectFixed(cUnit, rlSrc, r1);   /* Len */
             loadConstant(cUnit, r0, (int) classPtr );
@@ -3023,6 +3033,7 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
             ClassObject *classPtr =
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
             assert(classPtr != NULL);
+            flushAllRegs(cUnit);   /* Send everything to home location */
             loadValueDirectFixed(cUnit, rlSrc, r0);  /* Ref */
             loadConstant(cUnit, r2, (int) classPtr );
 //TUNING: compare to 0 primative to allow use of CB[N]Z
@@ -3281,14 +3292,23 @@ static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
         case OP_FILL_ARRAY_DATA: {
             RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
             // Making a call - use explicit registers
+            flushAllRegs(cUnit);   /* Send everything to home location */
             genExportPC(cUnit, mir);
             loadValueDirectFixed(cUnit, rlSrc, r0);
-            loadConstant(cUnit, r3, (int)dvmInterpHandleFillArrayData);
+            loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
             loadConstant(cUnit, r1, (mir->dalvikInsn.vB << 1) +
                  (int) (cUnit->method->insns + mir->offset));
             opReg(cUnit, kOpBlx, r2);
             clobberCallRegs(cUnit);
-            genZeroCheck(cUnit, r0, mir->offset, NULL);
+            /* generate a branch over if successful */
+            opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
+            ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
+            loadConstant(cUnit, r0,
+                         (int) (cUnit->method->insns + mir->offset));
+            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+            ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+            target->defMask = ENCODE_ALL;
+            branchOver->generic.target = (LIR *) target;
             break;
         }
         /*
@@ -3301,6 +3321,7 @@ static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
         case OP_PACKED_SWITCH:
         case OP_SPARSE_SWITCH: {
             RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
+            flushAllRegs(cUnit);   /* Send everything to home location */
             loadValueDirectFixed(cUnit, rlSrc, r1);
             lockAllTemps(cUnit);
             // Exit to the interpreter, setting up r4PC
@@ -3681,6 +3702,62 @@ static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
 }
 
 /*
+ * This operation is complex enough that we'll do it partly inline
+ * and partly with a handler.  NOTE: the handler uses hardcoded
+ * values for string object offsets and must be revisitied if the
+ * layout changes.
+ */
+static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
+{
+#if defined(USE_GLOBAL_STRING_DEFS)
+    return false;
+#else
+    ArmLIR *rollback;
+    RegLocation rlThis = getSrcLoc(cUnit, mir, 0);
+    RegLocation rlComp = getSrcLoc(cUnit, mir, 1);
+
+    loadValueDirectFixed(cUnit, rlThis, r0);
+    loadValueDirectFixed(cUnit, rlComp, r1);
+    /* Test objects for NULL */
+    rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
+    genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
+    /*
+     * TUNING: we could check for object pointer equality before invoking
+     * handler. Unclear whether the gain would be worth the added code size
+     * expansion.
+     */
+    genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
+    storeValue(cUnit, inlinedTarget(cUnit, mir, false), getReturnLoc(cUnit));
+    return true;
+#endif
+}
+
+static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
+{
+#if defined(USE_GLOBAL_STRING_DEFS)
+    return false;
+#else
+    RegLocation rlThis = getSrcLoc(cUnit, mir, 0);
+    RegLocation rlChar = getSrcLoc(cUnit, mir, 1);
+
+    loadValueDirectFixed(cUnit, rlThis, r0);
+    loadValueDirectFixed(cUnit, rlChar, r1);
+    if (!singleI) {
+        RegLocation rlStart = getSrcLoc(cUnit, mir, 2);
+        loadValueDirectFixed(cUnit, rlStart, r2);
+    } else {
+        loadConstant(cUnit, r2, 0);
+    }
+    /* Test objects for NULL */
+    genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
+    genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
+    storeValue(cUnit, inlinedTarget(cUnit, mir, false), getReturnLoc(cUnit));
+    return true;
+#endif
+}
+
+
+/*
  * NOTE: We assume here that the special native inline routines
  * are side-effect free.  By making this assumption, we can safely
  * re-execute the routine from the interpreter if it decides it
@@ -3717,9 +3794,6 @@ static bool handleFmt3inline(CompilationUnit *cUnit, MIR *mir)
                         return false;
                     else
                         break;   /* Handle with C routine */
-                case INLINE_MATH_COS:
-                case INLINE_MATH_SIN:
-                        break;   /* Handle with C routine */
                 case INLINE_MATH_ABS_FLOAT:
                     if (genInlinedAbsFloat(cUnit, mir))
                         return false;
@@ -3731,13 +3805,28 @@ static bool handleFmt3inline(CompilationUnit *cUnit, MIR *mir)
                     else
                         break;
                 case INLINE_STRING_COMPARETO:
-                case INLINE_STRING_EQUALS:
+                    if (genInlinedCompareTo(cUnit, mir))
+                        return false;
+                    else
+                        break;
                 case INLINE_STRING_INDEXOF_I:
+                    if (genInlinedIndexOf(cUnit, mir, true /* I */))
+                        return false;
+                    else
+                        break;
                 case INLINE_STRING_INDEXOF_II:
-                    break;
+                    if (genInlinedIndexOf(cUnit, mir, false /* I */))
+                        return false;
+                    else
+                        break;
+                case INLINE_STRING_EQUALS:
+                case INLINE_MATH_COS:
+                case INLINE_MATH_SIN:
+                    break;   /* Handle with C routine */
                 default:
                     dvmAbort();
             }
+            flushAllRegs(cUnit);   /* Send everything to home location */
             clobberCallRegs(cUnit);
             clobberReg(cUnit, r4PC);
             clobberReg(cUnit, r7);
index 8b687d7..1608920 100644 (file)
@@ -53,3 +53,5 @@ JIT_TEMPLATE(SQRT_DOUBLE_VFP)
 JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
 JIT_TEMPLATE(SAVE_STATE)
 JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_STRING_COMPARETO.S b/vm/compiler/template/armv5te/TEMPLATE_STRING_COMPARETO.S
new file mode 100644 (file)
index 0000000..85b2a9f
--- /dev/null
@@ -0,0 +1,93 @@
+    /*
+     * String's compareTo.
+     *
+     * Requires r0/r1 to have been previously checked for null.  Will
+     * return negative if this's string is < comp, 0 if they are the
+     * same and positive if >.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync with definitions in UtfString.h.  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   this object pointer
+     *    r1:   comp object pointer
+     *
+     */
+
+    mov    r2, r0         @ this to r2, opening up r0 for return value
+    subs   r0, r2, r1     @ Same?
+    bxeq   lr
+
+    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
+    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
+    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
+    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
+    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
+    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r2/r1
+     *    offset: r4/r9
+     *    count:  r7/r10
+     * We're going to compute
+     *    r11 <- countDiff
+     *    r10 <- minCount
+     */
+     subs  r11, r7, r10
+     movls r10, r7
+
+     /* Now, build pointers to the string data */
+     add   r2, r2, r4, lsl #1
+     add   r1, r1, r9, lsl #1
+     /*
+      * Note: data pointers point to previous element so we can use pre-index
+      * mode with base writeback.
+      */
+     add   r2, #16-2   @ offset to contents[-1]
+     add   r1, #16-2   @ offset to contents[-1]
+
+     /*
+      * At this point we have:
+      *   r2: *this string data
+      *   r1: *comp string data
+      *   r10: iteration count for comparison
+      *   r11: value to return if the first part of the string is equal
+      *   r0: reserved for result
+      *   r3, r4, r7, r8, r9, r12 available for loading string data
+      */
+
+    cmp   r10, #3
+    blt   do_remainder
+loopback_triple:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    ldrh  r7, [r2, #2]!
+    ldrh  r8, [r1, #2]!
+    ldrh  r9, [r2, #2]!
+    ldrh  r12,[r1, #2]!
+    subs  r0, r3, r4
+    subeqs  r0, r7, r8
+    subeqs  r0, r9, r12
+    bxne  lr
+    subs  r10, #3
+    bgt   loopback_triple
+
+do_remainder:
+    cmp   r10, #0
+    beq   returnDiff
+
+loopback_single:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    subs  r0, r3, r4
+    bxne  lr
+    subs  r10, #1
+    bne     loopback_single
+
+returnDiff:
+    mov   r0, r11
+    bx    lr
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_STRING_INDEXOF.S b/vm/compiler/template/armv5te/TEMPLATE_STRING_INDEXOF.S
new file mode 100644 (file)
index 0000000..685ccc6
--- /dev/null
@@ -0,0 +1,100 @@
+    /*
+     * String's indexOf.
+     *
+     * Requires r0 to have been previously checked for null.  Will
+     * return index of match of r1 in r0.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync wth definitions in UtfString.h  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   string object pointer
+     *    r1:   char to match
+     *    r2:   Starting offset in string data
+     */
+
+    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
+    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
+    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r0
+     *    offset: r7
+     *    count:  r8
+     */
+
+     /* Clamp start to [0..count] */
+     cmp   r2, #0
+     movlt r2, #0
+     cmp   r2, r8
+     movgt r2, r0
+
+     /* Fold start & offset, and set data pointer to contents[-1] */
+     add   r2, r7
+     add   r0, r0, r2, lsl #1
+     add   r0, #16-2   @ offset to contents[-1]
+     add   r2, r0, #2  @ remember true start of data
+
+     /*
+      * At this point we have:
+      *   r0: *next[-1] char to test
+      *   r2: *start
+      *   r1: char to compare
+      *   r8: max count
+      *   r3, r4, r7, r9, r12 available for loading string data
+      */
+
+    /* Unroll x 4 */
+
+    cmp   r8, #4
+    blt   do_rest
+loopback_quad:
+    ldrh  r3, [r0, #2]!
+    ldrh  r4, [r0, #2]!
+    ldrh  r7, [r0, #2]!
+    ldrh  r9, [r0, #2]!
+    cmp   r3, r1
+    beq   match_0
+    cmp   r4, r1
+    beq   match_1
+    cmp   r7, r1
+    beq   match_2
+    cmp   r9, r1
+    beq   match_3
+    subs  r8, #4
+    bgt   loopback_quad
+
+do_rest:
+    cmp   r8, #0
+    beq   no_match
+
+loopback_indexof:
+    ldrh  r3, [r0, #2]!
+    cmp   r3, r1
+    beq   match_3
+    subs  r8, #1
+    bne     loopback_indexof
+
+no_match:
+    mov   r0, #-1
+    bx    lr
+
+match_0:
+    sub   r0, #6
+    sub   r0, r2
+    bx    lr
+match_1:
+    sub   r0, #4
+    sub   r0, r2
+    bx    lr
+match_2:
+    sub   r0, #2
+    sub   r0, r2
+    bx    lr
+match_3:
+    sub   r0, r2
+    bx    lr
+
index 899c511..88cc60a 100644 (file)
@@ -38,3 +38,5 @@ JIT_TEMPLATE(USHR_LONG)
 JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
 JIT_TEMPLATE(SAVE_STATE)
 JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
index 8b687d7..1608920 100644 (file)
@@ -53,3 +53,5 @@ JIT_TEMPLATE(SQRT_DOUBLE_VFP)
 JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
 JIT_TEMPLATE(SAVE_STATE)
 JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
index ab3ff90..b5ca397 100644 (file)
@@ -43,6 +43,8 @@ op-start armv5te-vfp
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
     op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
+    op TEMPLATE_STRING_COMPARETO armv5te
+    op TEMPLATE_STRING_INDEXOF armv5te
 
 op-end
 
index aed0fa7..1d3d331 100644 (file)
@@ -43,6 +43,8 @@ op-start armv5te-vfp
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
     op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
+    op TEMPLATE_STRING_COMPARETO armv5te
+    op TEMPLATE_STRING_INDEXOF armv5te
 
 op-end
 
index 64a050b..797a2fc 100644 (file)
@@ -1072,6 +1072,211 @@ dvmCompiler_TEMPLATE_RESTORE_STATE:
     ldmia   r0, {r0-r12}
     bx      lr
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+    /*
+     * String's compareTo.
+     *
+     * Requires r0/r1 to have been previously checked for null.  Will
+     * return negative if this's string is < comp, 0 if they are the
+     * same and positive if >.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync with definitions in UtfString.h.  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   this object pointer
+     *    r1:   comp object pointer
+     *
+     */
+
+    mov    r2, r0         @ this to r2, opening up r0 for return value
+    subs   r0, r2, r1     @ Same?
+    bxeq   lr
+
+    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
+    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
+    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
+    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
+    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
+    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r2/r1
+     *    offset: r4/r9
+     *    count:  r7/r10
+     * We're going to compute
+     *    r11 <- countDiff
+     *    r10 <- minCount
+     */
+     subs  r11, r7, r10
+     movls r10, r7
+
+     /* Now, build pointers to the string data */
+     add   r2, r2, r4, lsl #1
+     add   r1, r1, r9, lsl #1
+     /*
+      * Note: data pointers point to previous element so we can use pre-index
+      * mode with base writeback.
+      */
+     add   r2, #16-2   @ offset to contents[-1]
+     add   r1, #16-2   @ offset to contents[-1]
+
+     /*
+      * At this point we have:
+      *   r2: *this string data
+      *   r1: *comp string data
+      *   r10: iteration count for comparison
+      *   r11: value to return if the first part of the string is equal
+      *   r0: reserved for result
+      *   r3, r4, r7, r8, r9, r12 available for loading string data
+      */
+
+    cmp   r10, #3
+    blt   do_remainder
+loopback_triple:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    ldrh  r7, [r2, #2]!
+    ldrh  r8, [r1, #2]!
+    ldrh  r9, [r2, #2]!
+    ldrh  r12,[r1, #2]!
+    subs  r0, r3, r4
+    subeqs  r0, r7, r8
+    subeqs  r0, r9, r12
+    bxne  lr
+    subs  r10, #3
+    bgt   loopback_triple
+
+do_remainder:
+    cmp   r10, #0
+    beq   returnDiff
+
+loopback_single:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    subs  r0, r3, r4
+    bxne  lr
+    subs  r10, #1
+    bne     loopback_single
+
+returnDiff:
+    mov   r0, r11
+    bx    lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+    /*
+     * String's indexOf.
+     *
+     * Requires r0 to have been previously checked for null.  Will
+     * return index of match of r1 in r0.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync wth definitions in UtfString.h  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   string object pointer
+     *    r1:   char to match
+     *    r2:   Starting offset in string data
+     */
+
+    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
+    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
+    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r0
+     *    offset: r7
+     *    count:  r8
+     */
+
+     /* Clamp start to [0..count] */
+     cmp   r2, #0
+     movlt r2, #0
+     cmp   r2, r8
+     movgt r2, r0
+
+     /* Fold start & offset, and set data pointer to contents[-1] */
+     add   r2, r7
+     add   r0, r0, r2, lsl #1
+     add   r0, #16-2   @ offset to contents[-1]
+     add   r2, r0, #2  @ remember true start of data
+
+     /*
+      * At this point we have:
+      *   r0: *next[-1] char to test
+      *   r2: *start
+      *   r1: char to compare
+      *   r8: max count
+      *   r3, r4, r7, r9, r12 available for loading string data
+      */
+
+    /* Unroll x 4 */
+
+    cmp   r8, #4
+    blt   do_rest
+loopback_quad:
+    ldrh  r3, [r0, #2]!
+    ldrh  r4, [r0, #2]!
+    ldrh  r7, [r0, #2]!
+    ldrh  r9, [r0, #2]!
+    cmp   r3, r1
+    beq   match_0
+    cmp   r4, r1
+    beq   match_1
+    cmp   r7, r1
+    beq   match_2
+    cmp   r9, r1
+    beq   match_3
+    subs  r8, #4
+    bgt   loopback_quad
+
+do_rest:
+    cmp   r8, #0
+    beq   no_match
+
+loopback_indexof:
+    ldrh  r3, [r0, #2]!
+    cmp   r3, r1
+    beq   match_3
+    subs  r8, #1
+    bne     loopback_indexof
+
+no_match:
+    mov   r0, #-1
+    bx    lr
+
+match_0:
+    sub   r0, #6
+    sub   r0, r2
+    bx    lr
+match_1:
+    sub   r0, #4
+    sub   r0, r2
+    bx    lr
+match_2:
+    sub   r0, #2
+    sub   r0, r2
+    bx    lr
+match_3:
+    sub   r0, r2
+    bx    lr
+
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
index 803f53b..340b05d 100644 (file)
@@ -797,6 +797,211 @@ dvmCompiler_TEMPLATE_RESTORE_STATE:
     ldmia   r0, {r0-r12}
     bx      lr
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+    /*
+     * String's compareTo.
+     *
+     * Requires r0/r1 to have been previously checked for null.  Will
+     * return negative if this's string is < comp, 0 if they are the
+     * same and positive if >.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync with definitions in UtfString.h.  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   this object pointer
+     *    r1:   comp object pointer
+     *
+     */
+
+    mov    r2, r0         @ this to r2, opening up r0 for return value
+    subs   r0, r2, r1     @ Same?
+    bxeq   lr
+
+    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
+    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
+    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
+    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
+    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
+    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r2/r1
+     *    offset: r4/r9
+     *    count:  r7/r10
+     * We're going to compute
+     *    r11 <- countDiff
+     *    r10 <- minCount
+     */
+     subs  r11, r7, r10
+     movls r10, r7
+
+     /* Now, build pointers to the string data */
+     add   r2, r2, r4, lsl #1
+     add   r1, r1, r9, lsl #1
+     /*
+      * Note: data pointers point to previous element so we can use pre-index
+      * mode with base writeback.
+      */
+     add   r2, #16-2   @ offset to contents[-1]
+     add   r1, #16-2   @ offset to contents[-1]
+
+     /*
+      * At this point we have:
+      *   r2: *this string data
+      *   r1: *comp string data
+      *   r10: iteration count for comparison
+      *   r11: value to return if the first part of the string is equal
+      *   r0: reserved for result
+      *   r3, r4, r7, r8, r9, r12 available for loading string data
+      */
+
+    cmp   r10, #3
+    blt   do_remainder
+loopback_triple:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    ldrh  r7, [r2, #2]!
+    ldrh  r8, [r1, #2]!
+    ldrh  r9, [r2, #2]!
+    ldrh  r12,[r1, #2]!
+    subs  r0, r3, r4
+    subeqs  r0, r7, r8
+    subeqs  r0, r9, r12
+    bxne  lr
+    subs  r10, #3
+    bgt   loopback_triple
+
+do_remainder:
+    cmp   r10, #0
+    beq   returnDiff
+
+loopback_single:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    subs  r0, r3, r4
+    bxne  lr
+    subs  r10, #1
+    bne     loopback_single
+
+returnDiff:
+    mov   r0, r11
+    bx    lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+    /*
+     * String's indexOf.
+     *
+     * Requires r0 to have been previously checked for null.  Will
+     * return index of match of r1 in r0.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync wth definitions in UtfString.h  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   string object pointer
+     *    r1:   char to match
+     *    r2:   Starting offset in string data
+     */
+
+    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
+    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
+    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r0
+     *    offset: r7
+     *    count:  r8
+     */
+
+     /* Clamp start to [0..count] */
+     cmp   r2, #0
+     movlt r2, #0
+     cmp   r2, r8
+     movgt r2, r0
+
+     /* Fold start & offset, and set data pointer to contents[-1] */
+     add   r2, r7
+     add   r0, r0, r2, lsl #1
+     add   r0, #16-2   @ offset to contents[-1]
+     add   r2, r0, #2  @ remember true start of data
+
+     /*
+      * At this point we have:
+      *   r0: *next[-1] char to test
+      *   r2: *start
+      *   r1: char to compare
+      *   r8: max count
+      *   r3, r4, r7, r9, r12 available for loading string data
+      */
+
+    /* Unroll x 4 */
+
+    cmp   r8, #4
+    blt   do_rest
+loopback_quad:
+    ldrh  r3, [r0, #2]!
+    ldrh  r4, [r0, #2]!
+    ldrh  r7, [r0, #2]!
+    ldrh  r9, [r0, #2]!
+    cmp   r3, r1
+    beq   match_0
+    cmp   r4, r1
+    beq   match_1
+    cmp   r7, r1
+    beq   match_2
+    cmp   r9, r1
+    beq   match_3
+    subs  r8, #4
+    bgt   loopback_quad
+
+do_rest:
+    cmp   r8, #0
+    beq   no_match
+
+loopback_indexof:
+    ldrh  r3, [r0, #2]!
+    cmp   r3, r1
+    beq   match_3
+    subs  r8, #1
+    bne     loopback_indexof
+
+no_match:
+    mov   r0, #-1
+    bx    lr
+
+match_0:
+    sub   r0, #6
+    sub   r0, r2
+    bx    lr
+match_1:
+    sub   r0, #4
+    sub   r0, r2
+    bx    lr
+match_2:
+    sub   r0, #2
+    sub   r0, r2
+    bx    lr
+match_3:
+    sub   r0, r2
+    bx    lr
+
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
index b597905..fca0d67 100644 (file)
@@ -1072,6 +1072,211 @@ dvmCompiler_TEMPLATE_RESTORE_STATE:
     ldmia   r0, {r0-r12}
     bx      lr
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+    /*
+     * String's compareTo.
+     *
+     * Requires r0/r1 to have been previously checked for null.  Will
+     * return negative if this's string is < comp, 0 if they are the
+     * same and positive if >.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync with definitions in UtfString.h.  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   this object pointer
+     *    r1:   comp object pointer
+     *
+     */
+
+    mov    r2, r0         @ this to r2, opening up r0 for return value
+    subs   r0, r2, r1     @ Same?
+    bxeq   lr
+
+    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
+    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
+    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
+    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
+    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
+    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r2/r1
+     *    offset: r4/r9
+     *    count:  r7/r10
+     * We're going to compute
+     *    r11 <- countDiff
+     *    r10 <- minCount
+     */
+     subs  r11, r7, r10
+     movls r10, r7
+
+     /* Now, build pointers to the string data */
+     add   r2, r2, r4, lsl #1
+     add   r1, r1, r9, lsl #1
+     /*
+      * Note: data pointers point to previous element so we can use pre-index
+      * mode with base writeback.
+      */
+     add   r2, #16-2   @ offset to contents[-1]
+     add   r1, #16-2   @ offset to contents[-1]
+
+     /*
+      * At this point we have:
+      *   r2: *this string data
+      *   r1: *comp string data
+      *   r10: iteration count for comparison
+      *   r11: value to return if the first part of the string is equal
+      *   r0: reserved for result
+      *   r3, r4, r7, r8, r9, r12 available for loading string data
+      */
+
+    cmp   r10, #3
+    blt   do_remainder
+loopback_triple:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    ldrh  r7, [r2, #2]!
+    ldrh  r8, [r1, #2]!
+    ldrh  r9, [r2, #2]!
+    ldrh  r12,[r1, #2]!
+    subs  r0, r3, r4
+    subeqs  r0, r7, r8
+    subeqs  r0, r9, r12
+    bxne  lr
+    subs  r10, #3
+    bgt   loopback_triple
+
+do_remainder:
+    cmp   r10, #0
+    beq   returnDiff
+
+loopback_single:
+    ldrh  r3, [r2, #2]!
+    ldrh  r4, [r1, #2]!
+    subs  r0, r3, r4
+    bxne  lr
+    subs  r10, #1
+    bne     loopback_single
+
+returnDiff:
+    mov   r0, r11
+    bx    lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+    /*
+     * String's indexOf.
+     *
+     * Requires r0 to have been previously checked for null.  Will
+     * return index of match of r1 in r0.
+     *
+     * IMPORTANT NOTE:
+     *
+     * This code relies on hard-coded offsets for string objects, and must be
+     * kept in sync wth definitions in UtfString.h  See asm-constants.h
+     *
+     * On entry:
+     *    r0:   string object pointer
+     *    r1:   char to match
+     *    r2:   Starting offset in string data
+     */
+
+    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
+    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
+    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
+
+    /*
+     * At this point, we have:
+     *    value:  r0
+     *    offset: r7
+     *    count:  r8
+     */
+
+     /* Clamp start to [0..count] */
+     cmp   r2, #0
+     movlt r2, #0
+     cmp   r2, r8
+     movgt r2, r0
+
+     /* Fold start & offset, and set data pointer to contents[-1] */
+     add   r2, r7
+     add   r0, r0, r2, lsl #1
+     add   r0, #16-2   @ offset to contents[-1]
+     add   r2, r0, #2  @ remember true start of data
+
+     /*
+      * At this point we have:
+      *   r0: *next[-1] char to test
+      *   r2: *start
+      *   r1: char to compare
+      *   r8: max count
+      *   r3, r4, r7, r9, r12 available for loading string data
+      */
+
+    /* Unroll x 4 */
+
+    cmp   r8, #4
+    blt   do_rest
+loopback_quad:
+    ldrh  r3, [r0, #2]!
+    ldrh  r4, [r0, #2]!
+    ldrh  r7, [r0, #2]!
+    ldrh  r9, [r0, #2]!
+    cmp   r3, r1
+    beq   match_0
+    cmp   r4, r1
+    beq   match_1
+    cmp   r7, r1
+    beq   match_2
+    cmp   r9, r1
+    beq   match_3
+    subs  r8, #4
+    bgt   loopback_quad
+
+do_rest:
+    cmp   r8, #0
+    beq   no_match
+
+loopback_indexof:
+    ldrh  r3, [r0, #2]!
+    cmp   r3, r1
+    beq   match_3
+    subs  r8, #1
+    bne     loopback_indexof
+
+no_match:
+    mov   r0, #-1
+    bx    lr
+
+match_0:
+    sub   r0, #6
+    sub   r0, r2
+    bx    lr
+match_1:
+    sub   r0, #4
+    sub   r0, r2
+    bx    lr
+match_2:
+    sub   r0, #2
+    sub   r0, r2
+    bx    lr
+match_3:
+    sub   r0, r2
+    bx    lr
+
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
index 9dbf6e8..bb6246b 100644 (file)
@@ -229,6 +229,12 @@ MTERP_OFFSET(offArrayObject_contents,   ArrayObject, contents, 16)
 MTERP_OFFSET(offArrayObject_contents,   ArrayObject, contents, 12)
 #endif
 
+/* String fields */
+MTERP_CONSTANT(STRING_FIELDOFF_VALUE,     8)
+MTERP_CONSTANT(STRING_FIELDOFF_HASHCODE, 12)
+MTERP_CONSTANT(STRING_FIELDOFF_OFFSET,   16)
+MTERP_CONSTANT(STRING_FIELDOFF_COUNT,    20)
+
 /* ClassObject fields */
 MTERP_OFFSET(offClassObject_descriptor, ClassObject, descriptor, 24)
 MTERP_OFFSET(offClassObject_accessFlags, ClassObject, accessFlags, 32)