Avoid use of std::string where we have const char*.
Removing the ClassHelper caused std::string creation for all calls to
Class::GetDescriptor and a significant performance regression. Make the
std::string an out argument so the caller can maintain it and its life time
while allowing GetDescriptor to return the common const char* case.
Don't generate GC maps when compilation is disabled.
Remove other uses of std::string that are occuring on critical paths.
Use the cheaper SkipClass in CompileMethod in CompilerDriver.
Specialize the utf8 as utf16 comparison code for the common shorter byte
encoding.
Force a bit of inlining, remove some UNLIKELYs (they are prone to pessimizing
code), add some LIKELYs.
x86-64 host 1-thread interpret-only of 57 apks:
Before: 29.539s
After: 23.467s
Regular compile:
Before: 1m35.347s
After: 1m20.056s
Bug: 16853450
Change-Id: Ic705ea24784bee24ab80084d06174cbf87d557ad
diff --git a/runtime/utf-inl.h b/runtime/utf-inl.h
index d8c258b..1373d17 100644
--- a/runtime/utf-inl.h
+++ b/runtime/utf-inl.h
@@ -40,20 +40,60 @@
inline int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1,
const char* utf8_2) {
- for (;;) {
- if (*utf8_1 == '\0') {
- return (*utf8_2 == '\0') ? 0 : -1;
- } else if (*utf8_2 == '\0') {
+ uint16_t c1, c2;
+ do {
+ c1 = *utf8_1;
+ c2 = *utf8_2;
+ // Did we reach a terminating character?
+ if (c1 == 0) {
+ return (c2 == 0) ? 0 : -1;
+ } else if (c2 == 0) {
return 1;
}
-
- int c1 = GetUtf16FromUtf8(&utf8_1);
- int c2 = GetUtf16FromUtf8(&utf8_2);
-
- if (c1 != c2) {
- return c1 > c2 ? 1 : -1;
+ // Assume 1-byte value and handle all cases first.
+ utf8_1++;
+ utf8_2++;
+ if ((c1 & 0x80) == 0) {
+ if (c1 == c2) {
+ // Matching 1-byte values.
+ continue;
+ } else {
+ // Non-matching values.
+ if ((c2 & 0x80) == 0) {
+ // 1-byte value, do nothing.
+ } else if ((c2 & 0x20) == 0) {
+ // 2-byte value.
+ c2 = ((c2 & 0x1f) << 6) | (*utf8_2 & 0x3f);
+ } else {
+ // 3-byte value.
+ c2 = ((c2 & 0x0f) << 12) | ((utf8_2[0] & 0x3f) << 6) | (utf8_2[1] & 0x3f);
+ }
+ return static_cast<int>(c1) - static_cast<int>(c2);
+ }
}
- }
+ // Non-matching or multi-byte values.
+ if ((c1 & 0x20) == 0) {
+ // 2-byte value.
+ c1 = ((c1 & 0x1f) << 6) | (*utf8_1 & 0x3f);
+ utf8_1++;
+ } else {
+ // 3-byte value.
+ c1 = ((c1 & 0x0f) << 12) | ((utf8_1[0] & 0x3f) << 6) | (utf8_1[1] & 0x3f);
+ utf8_1 += 2;
+ }
+ if ((c2 & 0x80) == 0) {
+ // 1-byte value, do nothing.
+ } else if ((c2 & 0x20) == 0) {
+ // 2-byte value.
+ c2 = ((c2 & 0x1f) << 6) | (*utf8_2 & 0x3f);
+ utf8_2++;
+ } else {
+ // 3-byte value.
+ c2 = ((c2 & 0x0f) << 12) | ((utf8_2[0] & 0x3f) << 6) | (utf8_2[1] & 0x3f);
+ utf8_2 += 2;
+ }
+ } while (c1 == c2);
+ return static_cast<int>(c1) - static_cast<int>(c2);
}
} // namespace art