diff options
author | Andreas Gampe <agampe@google.com> | 2014-05-01 23:42:21 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-05-01 23:42:21 +0000 |
commit | 608168b380b741e2c7e1a2b0b568c0738986166b (patch) | |
tree | 69c40cc3fbf71ec82879d855fb5a450db4773852 /runtime | |
parent | 43221f789244a898dc9f14e8b063d4c73326b47a (diff) | |
parent | 315ccab0d190af0482d9e656c66a184d87cab050 (diff) | |
download | art-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.cc | 75 | ||||
-rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 44 |
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 |