Jit - optimized inline string compareto, indexof; fill_array_data bug fix
Added flushAllRegs() prior to C handlers in preparation for upcoming support
for holding live/dirty values in physical registers.
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index 9563df1..8631580 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -1440,6 +1440,7 @@
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 @@
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 @@
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 @@
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 @@
*/
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 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 @@
* 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 @@
*/
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
/*
+ * 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 @@
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 @@
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);