Optimize JNI:GetStringRegion() for compressed strings.
Looking at the disassembly, it seems clang++ was unable to
optimize this properly, probably due to possible aliasing,
despite inlining the String::CharAt() and seeing all the
String::IsCompressed() expressions.
Explicitly use the fact that the string is compressed to
optimize the function and similar patterns in JNI.
Test: m test-art-host-gtest
Bug: 169674485
Change-Id: I35dd2540a1e79611a65d2d84f2a557c826120409
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 9e4cc7d..9aad198 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -1838,8 +1838,9 @@
} else {
CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
if (s->IsCompressed()) {
+ const uint8_t* src = s->GetValueCompressed() + start;
for (int i = 0; i < length; ++i) {
- buf[i] = static_cast<jchar>(s->CharAt(start+i));
+ buf[i] = static_cast<jchar>(src[i]);
}
} else {
const jchar* chars = static_cast<jchar*>(s->GetValue());
@@ -1862,8 +1863,9 @@
return;
}
if (s->IsCompressed()) {
+ const uint8_t* src = s->GetValueCompressed() + start;
for (int i = 0; i < length; ++i) {
- buf[i] = s->CharAt(start+i);
+ buf[i] = static_cast<jchar>(src[i]);
}
buf[length] = '\0';
} else {
@@ -1884,8 +1886,9 @@
jchar* chars = new jchar[s->GetLength()];
if (s->IsCompressed()) {
int32_t length = s->GetLength();
+ const uint8_t* src = s->GetValueCompressed();
for (int i = 0; i < length; ++i) {
- chars[i] = s->CharAt(i);
+ chars[i] = static_cast<jchar>(src[i]);
}
} else {
memcpy(chars, s->GetValue(), sizeof(jchar) * s->GetLength());
@@ -1920,9 +1923,10 @@
*is_copy = JNI_TRUE;
}
int32_t length = s->GetLength();
+ const uint8_t* src = s->GetValueCompressed();
jchar* chars = new jchar[length];
for (int i = 0; i < length; ++i) {
- chars[i] = s->CharAt(i);
+ chars[i] = static_cast<jchar>(src[i]);
}
return chars;
} else {
@@ -1978,8 +1982,9 @@
char* bytes = new char[byte_count + 1];
CHECK(bytes != nullptr); // bionic aborts anyway.
if (s->IsCompressed()) {
+ const uint8_t* src = s->GetValueCompressed();
for (size_t i = 0; i < byte_count; ++i) {
- bytes[i] = s->CharAt(i);
+ bytes[i] = src[i];
}
} else {
const uint16_t* chars = s->GetValue();