diff options
Diffstat (limited to 'vm/compiler/codegen/arm/CodegenDriver.c')
| -rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.c | 108 |
1 files changed, 90 insertions, 18 deletions
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c index 0a59ea42a..68d5b843a 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; } @@ -2960,7 +3020,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; @@ -2970,12 +3030,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); @@ -2985,8 +3041,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); @@ -2994,10 +3053,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); @@ -3087,6 +3162,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: @@ -3117,13 +3194,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; @@ -3929,13 +4001,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; } |
