Implemented inline of String indexOf and compareTo on x86.
Change-Id: Ia141d4900e9ab9dd563e718af0d10dcd445794cb
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index f1653aa..d75234e 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -813,7 +813,7 @@
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 @@
} 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 @@
/* 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 @@
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 638a7c3..09b26b9 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -856,7 +856,7 @@
*
* 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 37a023a..d8098b6 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -732,6 +732,100 @@
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 @@
// TODO: implement these!
UNIMPLEMENTED art_update_debugger
-UNIMPLEMENTED art_indexof
UNIMPLEMENTED art_memcmp16
-UNIMPLEMENTED art_string_compareto