summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-05-01 23:42:21 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-05-01 23:42:21 +0000
commit608168b380b741e2c7e1a2b0b568c0738986166b (patch)
tree69c40cc3fbf71ec82879d855fb5a450db4773852 /runtime
parent43221f789244a898dc9f14e8b063d4c73326b47a (diff)
parent315ccab0d190af0482d9e656c66a184d87cab050 (diff)
downloadart-608168b380b741e2c7e1a2b0b568c0738986166b.zip
art-608168b380b741e2c7e1a2b0b568c0738986166b.tar.gz
art-608168b380b741e2c7e1a2b0b568c0738986166b.tar.bz2
Merge "Implement art_quick_string_compareto entrypoint for x86-64"
Diffstat (limited to 'runtime')
-rw-r--r--runtime/arch/stub_test.cc75
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S44
2 files changed, 118 insertions, 1 deletions
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 7027b32..437beb5 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -633,4 +633,79 @@ TEST_F(StubTest, AllocObjectArray) {
#endif
}
+
+#if defined(__i386__) || defined(__arm__) || defined(__x86_64__)
+extern "C" void art_quick_string_compareto(void);
+#endif
+
+TEST_F(StubTest, StringCompareTo) {
+ TEST_DISABLED_FOR_HEAP_REFERENCE_POISONING();
+
+#if defined(__i386__) || defined(__arm__) || defined(__x86_64__)
+ // TODO: Check the "Unresolved" allocation stubs
+
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ // garbage is created during ClassLinker::Init
+
+ // Create some strings
+ // Use array so we can index into it and use a matrix for expected results
+ constexpr size_t string_count = 7;
+ const char* c[string_count] = { "", "", "a", "aa", "ab", "aac", "aac" };
+
+ SirtRef<mirror::String>* s[string_count];
+
+ for (size_t i = 0; i < string_count; ++i) {
+ s[i] = new SirtRef<mirror::String>(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(),
+ c[i]));
+ }
+
+ // TODO: wide characters
+
+ // Matrix of expectations. First component is first parameter. Note we only check against the
+ // sign, not the value.
+ int32_t expected[string_count][string_count] = {
+ { 0, 0, -1, -1, -1, -1, -1 }, // ""
+ { 0, 0, -1, -1, -1, -1, -1 }, // ""
+ { 1, 1, 0, -1, -1, -1, -1 }, // "a"
+ { 1, 1, 1, 0, -1, -1, -1 }, // "aa"
+ { 1, 1, 1, 1, 0, 1, 1 }, // "ab"
+ { 1, 1, 1, 1, -1, 0, 0 }, // "aac"
+ { 1, 1, 1, 1, -1, 0, 0 } // "aac"
+ // "" "" a aa ab aac aac
+ };
+
+ // Play with it...
+
+ for (size_t x = 0; x < string_count; ++x) {
+ for (size_t y = 0; y < string_count; ++y) {
+ // Test string_compareto x y
+ size_t result = Invoke3(reinterpret_cast<size_t>(s[x]->get()),
+ reinterpret_cast<size_t>(s[y]->get()), 0U,
+ reinterpret_cast<uintptr_t>(&art_quick_string_compareto), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+
+ // The result is a 32b signed integer
+ union {
+ size_t r;
+ int32_t i;
+ } conv;
+ conv.r = result;
+ int32_t e = expected[x][y];
+ EXPECT_TRUE(e == 0 ? conv.i == 0 : true) << "x=" << c[x] << " y=" << c[y];
+ EXPECT_TRUE(e < 0 ? conv.i < 0 : true) << "x=" << c[x] << " y=" << c[y];
+ EXPECT_TRUE(e > 0 ? conv.i > 0 : true) << "x=" << c[x] << " y=" << c[y];
+ }
+ }
+
+ // Tests done.
+#else
+ LOG(INFO) << "Skipping string_compareto as I don't know how to do that on " << kRuntimeISA;
+ // Force-print to std::cout so it's also outside the logcat.
+ std::cout << "Skipping string_compareto as I don't know how to do that on " << kRuntimeISA <<
+ std::endl;
+#endif
+}
+
} // namespace art
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 4fefd20..cac6cfd 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1169,5 +1169,47 @@ UNIMPLEMENTED art_quick_instrumentation_exit
UNIMPLEMENTED art_quick_deoptimize
UNIMPLEMENTED art_quick_indexof
-UNIMPLEMENTED art_quick_string_compareto
+
+ /*
+ * String's compareTo.
+ *
+ * On entry:
+ * rdi: this string object (known non-null)
+ * rsi: comp string object (known non-null)
+ */
+DEFINE_FUNCTION art_quick_string_compareto
+ movl STRING_COUNT_OFFSET(%edi), %r8d
+ movl STRING_COUNT_OFFSET(%esi), %r9d
+ movl STRING_VALUE_OFFSET(%edi), %r10d
+ movl STRING_VALUE_OFFSET(%esi), %r11d
+ movl STRING_OFFSET_OFFSET(%edi), %eax
+ movl STRING_OFFSET_OFFSET(%esi), %ecx
+ /* Build pointers to the start of string data */
+ leal STRING_DATA_OFFSET(%r10d, %eax, 2), %esi
+ leal STRING_DATA_OFFSET(%r11d, %ecx, 2), %edi
+ /* Calculate min length and count diff */
+ movl %r8d, %ecx
+ movl %r8d, %eax
+ subl %r9d, %eax
+ cmovg %r9d, %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
+ */
+ jecxz .Lkeep_length
+ repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx
+ jne .Lnot_equal
+.Lkeep_length:
+ ret
+ .balign 16
+.Lnot_equal:
+ movzwl -2(%esi), %eax // get last compared char from this string
+ movzwl -2(%edi), %ecx // get last compared char from comp string
+ subl %ecx, %eax // return the difference
+ ret
+END_FUNCTION art_quick_string_compareto
+
UNIMPLEMENTED art_quick_memcmp16