aboutsummaryrefslogtreecommitdiff
path: root/vm/compiler/codegen/arm/CodegenDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen/arm/CodegenDriver.c')
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c108
1 files changed, 90 insertions, 18 deletions
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index e9f00dda1..8522563b3 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1343,7 +1343,7 @@ static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
{
OpCode dalvikOpCode = mir->dalvikInsn.opCode;
if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
- ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
+ ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_E7))) {
LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
return true;
}
@@ -1898,6 +1898,57 @@ static int lowestSetBit(unsigned int x) {
return bit_posn;
}
+// Returns true if it added instructions to 'cUnit' to divide 'rlSrc' by 'lit'
+// and store the result in 'rlDest'.
+static bool handleEasyDivide(CompilationUnit *cUnit, OpCode dalvikOpCode,
+ RegLocation rlSrc, RegLocation rlDest, int lit)
+{
+ if (lit < 2 || !isPowerOfTwo(lit)) {
+ return false;
+ }
+ int k = lowestSetBit(lit);
+ if (k >= 30) {
+ // Avoid special cases.
+ return false;
+ }
+ bool div = (dalvikOpCode == OP_DIV_INT_LIT8 || dalvikOpCode == OP_DIV_INT_LIT16);
+ rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+ RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
+ if (div) {
+ int tReg = dvmCompilerAllocTemp(cUnit);
+ if (lit == 2) {
+ // Division by 2 is by far the most common division by constant.
+ opRegRegImm(cUnit, kOpLsr, tReg, rlSrc.lowReg, 32 - k);
+ opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
+ opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
+ } else {
+ opRegRegImm(cUnit, kOpAsr, tReg, rlSrc.lowReg, 31);
+ opRegRegImm(cUnit, kOpLsr, tReg, tReg, 32 - k);
+ opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
+ opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
+ }
+ } else {
+ int cReg = dvmCompilerAllocTemp(cUnit);
+ loadConstant(cUnit, cReg, lit - 1);
+ int tReg1 = dvmCompilerAllocTemp(cUnit);
+ int tReg2 = dvmCompilerAllocTemp(cUnit);
+ if (lit == 2) {
+ opRegRegImm(cUnit, kOpLsr, tReg1, rlSrc.lowReg, 32 - k);
+ opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
+ opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
+ opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
+ } else {
+ opRegRegImm(cUnit, kOpAsr, tReg1, rlSrc.lowReg, 31);
+ opRegRegImm(cUnit, kOpLsr, tReg1, tReg1, 32 - k);
+ opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
+ opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
+ opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
+ }
+ }
+ storeValue(cUnit, rlDest, rlResult);
+ return true;
+}
+
// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
// and store the result in 'rlDest'.
static bool handleEasyMultiply(CompilationUnit *cUnit,
@@ -2019,6 +2070,9 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
genInterpSingleStep(cUnit, mir);
return false;
}
+ if (handleEasyDivide(cUnit, dalvikOpCode, rlSrc, rlDest, lit)) {
+ return false;
+ }
dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r0);
dvmCompilerClobber(cUnit, r0);
@@ -2192,6 +2246,12 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
case OP_IPUT_BOOLEAN:
genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
break;
+ case OP_IGET_WIDE_VOLATILE:
+ case OP_IPUT_WIDE_VOLATILE:
+ case OP_SGET_WIDE_VOLATILE:
+ case OP_SPUT_WIDE_VOLATILE:
+ genInterpSingleStep(cUnit, mir);
+ break;
default:
return true;
}
@@ -2982,7 +3042,7 @@ static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
#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;
@@ -2992,12 +3052,8 @@ static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
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);
@@ -3007,8 +3063,11 @@ static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
#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);
@@ -3016,10 +3075,26 @@ static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
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);
@@ -3109,6 +3184,8 @@ static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
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:
@@ -3139,13 +3216,8 @@ static bool handleExecuteInline(CompilationUnit *cUnit, MIR *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:
- if (genInlinedIndexOf(cUnit, mir, false /* I */))
+ case INLINE_STRING_FASTINDEXOF_II:
+ if (genInlinedFastIndexOf(cUnit, mir))
return false;
else
break;
@@ -3951,13 +4023,13 @@ bool dvmCompilerDoWork(CompilerWorkOrder *work)
/* Start compilation with maximally allowed trace length */
res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
work->bailPtr);
- gDvmJit.printMe = oldPrintMe;;
+ gDvmJit.printMe = oldPrintMe;
break;
}
default:
res = false;
LOGE("Jit: unknown work order type");
- assert(0); // Bail if debug build, discard oteherwise
+ assert(0); // Bail if debug build, discard otherwise
}
return res;
}