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/class_linker_test.cc b/runtime/class_linker_test.cc
index 8d93265..69c281e 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -68,7 +68,8 @@
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(descriptor.c_str(), primitive->GetDescriptor().c_str());
+ std::string temp;
+ ASSERT_STREQ(descriptor.c_str(), primitive->GetDescriptor(&temp));
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
@@ -106,7 +107,8 @@
Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
Handle<mirror::Class> array(
hs.NewHandle(class_linker_->FindClass(self, array_descriptor.c_str(), loader)));
- EXPECT_STREQ(component_type.c_str(), array->GetComponentType()->GetDescriptor().c_str());
+ std::string temp;
+ EXPECT_STREQ(component_type.c_str(), array->GetComponentType()->GetDescriptor(&temp));
EXPECT_EQ(class_loader, array->GetClassLoader());
EXPECT_EQ(kAccFinal | kAccAbstract, (array->GetAccessFlags() & (kAccFinal | kAccAbstract)));
AssertArrayClass(array_descriptor, array);
@@ -118,13 +120,14 @@
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor().c_str());
+ std::string temp;
+ ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor(&temp));
EXPECT_TRUE(array->GetSuperClass() != NULL);
Thread* self = Thread::Current();
EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != NULL);
- ASSERT_TRUE(!array->GetComponentType()->GetDescriptor().empty());
+ ASSERT_GT(strlen(array->GetComponentType()->GetDescriptor(&temp)), 0U);
EXPECT_EQ(mirror::Class::kStatusInitialized, array->GetStatus());
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsLoaded());
@@ -148,9 +151,9 @@
ASSERT_TRUE(array->GetIfTable() != NULL);
mirror::Class* direct_interface0 = mirror::Class::GetDirectInterface(self, array, 0);
EXPECT_TRUE(direct_interface0 != nullptr);
- EXPECT_STREQ(direct_interface0->GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
+ EXPECT_STREQ(direct_interface0->GetDescriptor(&temp), "Ljava/lang/Cloneable;");
mirror::Class* direct_interface1 = mirror::Class::GetDirectInterface(self, array, 1);
- EXPECT_STREQ(direct_interface1->GetDescriptor().c_str(), "Ljava/io/Serializable;");
+ EXPECT_STREQ(direct_interface1->GetDescriptor(&temp), "Ljava/io/Serializable;");
mirror::Class* array_ptr = array->GetComponentType();
EXPECT_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
}
@@ -185,7 +188,8 @@
void AssertClass(const std::string& descriptor, Handle<mirror::Class> klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- EXPECT_STREQ(descriptor.c_str(), klass->GetDescriptor().c_str());
+ std::string temp;
+ EXPECT_STREQ(descriptor.c_str(), klass->GetDescriptor(&temp));
if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
} else {
@@ -201,8 +205,9 @@
EXPECT_FALSE(klass->IsArrayClass());
EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_TRUE(klass->IsInSamePackage(klass.Get()));
- EXPECT_TRUE(mirror::Class::IsInSamePackage(klass->GetDescriptor().c_str(),
- klass->GetDescriptor().c_str()));
+ std::string temp2;
+ EXPECT_TRUE(mirror::Class::IsInSamePackage(klass->GetDescriptor(&temp),
+ klass->GetDescriptor(&temp2)));
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
@@ -311,7 +316,8 @@
Handle<mirror::Class> klass(
hs.NewHandle(class_linker_->FindSystemClass(self, descriptor.c_str())));
ASSERT_TRUE(klass.Get() != nullptr);
- EXPECT_STREQ(descriptor.c_str(), klass.Get()->GetDescriptor().c_str());
+ std::string temp;
+ EXPECT_STREQ(descriptor.c_str(), klass.Get()->GetDescriptor(&temp));
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
AssertPrimitiveClass(descriptor, klass.Get());
@@ -671,7 +677,8 @@
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
- ASSERT_STREQ(JavaLangObject->GetDescriptor().c_str(), "Ljava/lang/Object;");
+ std::string temp;
+ ASSERT_STREQ(JavaLangObject->GetDescriptor(&temp), "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
@@ -715,7 +722,7 @@
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
- ASSERT_STREQ(MyClass->GetDescriptor().c_str(), "LMyClass;");
+ ASSERT_STREQ(MyClass->GetDescriptor(&temp), "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.Get(), MyClass->GetClassLoader());
@@ -860,7 +867,8 @@
EXPECT_EQ(9U, statics->NumStaticFields());
mirror::ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z");
- EXPECT_STREQ(s0->GetClass()->GetDescriptor().c_str(), "Ljava/lang/reflect/ArtField;");
+ std::string temp;
+ EXPECT_STREQ(s0->GetClass()->GetDescriptor(&temp), "Ljava/lang/reflect/ArtField;");
EXPECT_EQ(s0->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(statics.Get()));
s0->SetBoolean<false>(statics.Get(), false);
@@ -1051,10 +1059,11 @@
TEST_F(ClassLinkerTest, ClassRootDescriptors) {
ScopedObjectAccess soa(Thread::Current());
+ std::string temp;
for (int i = 0; i < ClassLinker::kClassRootsMax; i++) {
mirror::Class* klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
- EXPECT_TRUE(!klass->GetDescriptor().empty());
- EXPECT_STREQ(klass->GetDescriptor().c_str(),
+ EXPECT_GT(strlen(klass->GetDescriptor(&temp)), 0U);
+ EXPECT_STREQ(klass->GetDescriptor(&temp),
class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
}
}