diff options
| author | 2012-08-08 17:30:59 -0700 | |
|---|---|---|
| committer | 2012-08-10 09:52:15 -0700 | |
| commit | 86e4671975752b112b2e8969ac6652c72c8e86c7 (patch) | |
| tree | 44be48718a716ce58a7c087c33ddd264c7943450 | |
| parent | 46a23638436afdf17330870ef150f5b8eb66410c (diff) | |
Implemented inline of String indexOf and compareTo on x86.
Change-Id: Ia141d4900e9ab9dd563e718af0d10dcd445794cb
| -rw-r--r-- | src/compiler/codegen/GenInvoke.cc | 16 | ||||
| -rw-r--r-- | src/oat/runtime/arm/runtime_support_arm.S | 2 | ||||
| -rw-r--r-- | src/oat/runtime/x86/runtime_support_x86.S | 96 |
3 files changed, 109 insertions, 5 deletions
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index f1653aa4b0..d75234e38e 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -813,7 +813,7 @@ bool genInlinedDoubleCvt(CompilationUnit *cUnit, CallInfo* info) bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, bool zeroBased) { -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_X86) oatClobberCalleeSave(cUnit); oatLockCallTemps(cUnit); // Using fixed registers int regPtr = rARG0; @@ -830,13 +830,19 @@ bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, } else { loadValueDirectFixed(cUnit, rlStart, regStart); } +#if !defined(TARGET_X86) int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf)); +#endif genNullCheck(cUnit, rlObj.sRegLow, regPtr, info->optFlags); LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, (intptr_t)launchPad); opCmpImmBranch(cUnit, kCondGt, regChar, 0xFFFF, launchPad); +#if !defined(TARGET_X86) opReg(cUnit, kOpBlx, rTgt); +#else + opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pIndexOf)); +#endif LIR* resumeTgt = newLIR0(cUnit, kPseudoTargetLabel); launchPad->operands[2] = (uintptr_t)resumeTgt; // Record that we've already inlined & null checked @@ -853,7 +859,7 @@ bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, /* Fast string.compareTo(Ljava/lang/string;)I. */ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) { -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_X86) oatClobberCalleeSave(cUnit); oatLockCallTemps(cUnit); // Using fixed registers int regThis = rARG0; @@ -863,14 +869,20 @@ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) RegLocation rlCmp = info->args[1]; loadValueDirectFixed(cUnit, rlThis, regThis); loadValueDirectFixed(cUnit, rlCmp, regCmp); +#if !defined(TARGET_X86) int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo)); +#endif genNullCheck(cUnit, rlThis.sRegLow, regThis, info->optFlags); //TUNING: check if rlCmp.sRegLow is already null checked LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, (intptr_t)launchPad); opCmpImmBranch(cUnit, kCondEq, regCmp, 0, launchPad); +#if !defined(TARGET_X86) opReg(cUnit, kOpBlx, rTgt); +#else + opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo)); +#endif launchPad->operands[2] = 0; // No return possible // Record that we've already inlined & null checked info->optFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK); diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S index 638a7c31b5..09b26b96dd 100644 --- a/src/oat/runtime/arm/runtime_support_arm.S +++ b/src/oat/runtime/arm/runtime_support_arm.S @@ -856,7 +856,7 @@ art_indexof: * * On entry: * r0: string object (known non-null) - * r1: char to match + * r1: char to match (known <= 0xFFFF) * r2: Starting offset in string data */ diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S index 37a023a99f..d8098b672f 100644 --- a/src/oat/runtime/x86/runtime_support_x86.S +++ b/src/oat/runtime/x86/runtime_support_x86.S @@ -732,6 +732,100 @@ DEFINE_FUNCTION art_proxy_invoke_handler addl LITERAL(44), %esp // pop arguments RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception + /* + * String's indexOf. + * + * On entry: + * eax: string object (known non-null) + * ecx: char to match (known <= 0xFFFF) + * edx: Starting offset in string data + */ +DEFINE_FUNCTION art_indexof + pushl %edi // push callee save reg + mov STRING_COUNT_OFFSET(%eax), %ebx + mov STRING_VALUE_OFFSET(%eax), %edi + mov STRING_OFFSET_OFFSET(%eax), %eax + testl %edx, %edx // check if start < 0 + jl clamp_min +clamp_done: + cmpl %ebx, %edx // check if start >= count + jge not_found + lea STRING_DATA_OFFSET(%edi, %eax, 2), %edi // build a pointer to the start of string data + mov %edi, %eax // save a copy in eax to later compute result + lea (%edi, %edx, 2), %edi // build pointer to start of data to compare + subl %edx, %ebx // compute iteration count + /* + * At this point we have: + * eax: original start of string data + * ecx: char to compare + * ebx: length to compare + * edi: start of data to test + */ + mov %eax, %edx + mov %ecx, %eax // put char to match in %eax + mov %ebx, %ecx // put length to compare in %ecx + repne scasw // find %ax, starting at [%edi], up to length %ecx + jne not_found + subl %edx, %edi + sar LITERAL(1), %edi + decl %edi // index = ((curr_ptr - orig_ptr) / 2) - 1 + mov %edi, %eax + popl %edi // pop callee save reg + ret + .balign 16 +not_found: + mov LITERAL(-1), %eax // return -1 (not found) + popl %edi // pop callee save reg + ret +clamp_min: + xor %edx, %edx // clamp start to 0 + jmp clamp_done + + /* + * String's compareTo. + * + * On entry: + * eax: this string object (known non-null) + * ecx: comp string object (known non-null) + */ +DEFINE_FUNCTION art_string_compareto + pushl %esi // push callee save reg + pushl %edi // push callee save reg + mov STRING_COUNT_OFFSET(%eax), %edx + mov STRING_COUNT_OFFSET(%ecx), %ebx + mov STRING_VALUE_OFFSET(%eax), %esi + mov STRING_VALUE_OFFSET(%ecx), %edi + mov STRING_OFFSET_OFFSET(%eax), %eax + mov STRING_OFFSET_OFFSET(%ecx), %ecx + /* Build pointers to the start of string data */ + lea STRING_DATA_OFFSET(%esi, %eax, 2), %esi + lea STRING_DATA_OFFSET(%edi, %ecx, 2), %edi + /* Calculate min length and count diff */ + mov %edx, %ecx + mov %edx, %eax + subl %ebx, %eax + cmovg %ebx, %ecx + /* + * At this point we have: + * eax: value to return if first part of strings are equal + * ecx: minimum among the lengths of the two strings + * esi: pointer to this string data + * edi: pointer to comp string data + */ + repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx + jne not_equal + popl %edi // pop callee save reg + popl %esi // pop callee save reg + ret + .balign 16 +not_equal: + movzxw -2(%esi), %eax // get last compared char from this string + movzxw -2(%edi), %ecx // get last compared char from comp string + subl %ecx, %eax // return the difference + popl %edi // pop callee save reg + popl %esi // pop callee save reg + ret + MACRO1(UNIMPLEMENTED,name) .globl VAR(name, 0) ALIGN_FUNCTION_ENTRY @@ -741,6 +835,4 @@ END_MACRO // TODO: implement these! UNIMPLEMENTED art_update_debugger -UNIMPLEMENTED art_indexof UNIMPLEMENTED art_memcmp16 -UNIMPLEMENTED art_string_compareto |