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/utils.cc b/runtime/utils.cc
index 48d6cdf..b845f50 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -222,19 +222,20 @@
if (java_descriptor == NULL) {
return "null";
}
- return PrettyDescriptor(java_descriptor->ToModifiedUtf8());
+ return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
}
std::string PrettyDescriptor(mirror::Class* klass) {
if (klass == NULL) {
return "null";
}
- return PrettyDescriptor(klass->GetDescriptor());
+ std::string temp;
+ return PrettyDescriptor(klass->GetDescriptor(&temp));
}
-std::string PrettyDescriptor(const std::string& descriptor) {
+std::string PrettyDescriptor(const char* descriptor) {
// Count the number of '['s to get the dimensionality.
- const char* c = descriptor.c_str();
+ const char* c = descriptor;
size_t dim = 0;
while (*c == '[') {
dim++;
@@ -275,15 +276,14 @@
result.push_back(ch);
}
// ...and replace the semicolon with 'dim' "[]" pairs:
- while (dim--) {
+ for (size_t i = 0; i < dim; ++i) {
result += "[]";
}
return result;
}
std::string PrettyDescriptor(Primitive::Type type) {
- std::string descriptor_string(Primitive::Descriptor(type));
- return PrettyDescriptor(descriptor_string);
+ return PrettyDescriptor(Primitive::Descriptor(type));
}
std::string PrettyField(mirror::ArtField* f, bool with_type) {
@@ -341,8 +341,10 @@
} else {
++argument_length;
}
- std::string argument_descriptor(signature, argument_length);
- result += PrettyDescriptor(argument_descriptor);
+ {
+ std::string argument_descriptor(signature, argument_length);
+ result += PrettyDescriptor(argument_descriptor.c_str());
+ }
if (signature[argument_length] != ')') {
result += ", ";
}
@@ -410,9 +412,10 @@
if (obj->GetClass() == NULL) {
return "(raw)";
}
- std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
+ std::string temp;
+ std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor(&temp)));
if (obj->IsClass()) {
- result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor()) + ">";
+ result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor(&temp)) + ">";
}
return result;
}
@@ -622,11 +625,20 @@
std::string DescriptorToDot(const char* descriptor) {
size_t length = strlen(descriptor);
- if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
- std::string result(descriptor + 1, length - 2);
- std::replace(result.begin(), result.end(), '/', '.');
- return result;
+ if (length > 1) {
+ if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
+ // Descriptors have the leading 'L' and trailing ';' stripped.
+ std::string result(descriptor + 1, length - 2);
+ std::replace(result.begin(), result.end(), '/', '.');
+ return result;
+ } else {
+ // For arrays the 'L' and ';' remain intact.
+ std::string result(descriptor);
+ std::replace(result.begin(), result.end(), '/', '.');
+ return result;
+ }
}
+ // Do nothing for non-class/array descriptors.
return descriptor;
}