diff options
author | Ian Rogers <irogers@google.com> | 2014-08-12 02:30:58 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-08-12 16:08:05 -0700 |
commit | 1ff3c98775a4577cf053dba9a0c2d5c21c07b298 (patch) | |
tree | 2d09c27c69678b53b4c9dc486024f3547efd4bca /runtime/mirror | |
parent | 99c251bbd225dd97d0deece29559a430b12a0b66 (diff) | |
download | art-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.tar.gz art-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.tar.bz2 art-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.zip |
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
Diffstat (limited to 'runtime/mirror')
-rw-r--r-- | runtime/mirror/art_method-inl.h | 2 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/art_method.h | 4 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 6 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 50 | ||||
-rw-r--r-- | runtime/mirror/class.h | 8 | ||||
-rw-r--r-- | runtime/mirror/object_test.cc | 5 |
7 files changed, 45 insertions, 32 deletions
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 0dd158822b..06700e6d51 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -417,7 +417,7 @@ inline const Signature ArtMethod::GetSignature() { return Signature::NoSignature(); } -inline const char* ArtMethod::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +inline const char* ArtMethod::GetName() { mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); uint32_t dex_method_idx = method->GetDexMethodIndex(); if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 8eacb1c3d7..e88a3900b6 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -27,7 +27,7 @@ #include "interpreter/interpreter.h" #include "jni_internal.h" #include "mapping_table.h" -#include "method_helper.h" +#include "method_helper-inl.h" #include "object_array-inl.h" #include "object_array.h" #include "object-inl.h" diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 4ebceff155..fa592c29b5 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -446,7 +446,7 @@ class MANAGED ArtMethod FINAL : public Object { const Signature GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ALWAYS_INLINE const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const DexFile::CodeItem* GetCodeItem() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -473,7 +473,7 @@ class MANAGED ArtMethod FINAL : public Object { mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); protected: // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index c3754d7967..b0ff7eaa42 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -649,11 +649,11 @@ inline const DexFile& Class::GetDexFile() { } inline bool Class::DescriptorEquals(const char* match) { - if (UNLIKELY(IsArrayClass())) { + if (IsArrayClass()) { return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1); - } else if (UNLIKELY(IsPrimitive())) { + } else if (IsPrimitive()) { return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0; - } else if (UNLIKELY(IsProxyClass())) { + } else if (IsProxyClass()) { return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match; } else { const DexFile& dex_file = GetDexFile(); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index f29ba73d56..5b8eb829f5 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -90,15 +90,21 @@ void Class::SetStatus(Status new_status, Thread* self) { Class* eiie_class; // Do't attempt to use FindClass if we have an OOM error since this can try to do more // allocations and may cause infinite loops. - if (old_exception.Get() == nullptr || - old_exception->GetClass()->GetDescriptor() != "Ljava/lang/OutOfMemoryError;") { + bool throw_eiie = (old_exception.Get() == nullptr); + if (!throw_eiie) { + std::string temp; + const char* old_exception_descriptor = old_exception->GetClass()->GetDescriptor(&temp); + throw_eiie = (strcmp(old_exception_descriptor, "Ljava/lang/OutOfMemoryError;") != 0); + } + if (throw_eiie) { // Clear exception to call FindSystemClass. self->ClearException(); eiie_class = Runtime::Current()->GetClassLinker()->FindSystemClass( self, "Ljava/lang/ExceptionInInitializerError;"); CHECK(!self->IsExceptionPending()); // Only verification errors, not initialization problems, should set a verify error. - // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case. + // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that + // case. Class* exception_class = old_exception->GetClass(); if (!eiie_class->IsAssignableFrom(exception_class)) { SetVerifyErrorClass(exception_class); @@ -163,7 +169,8 @@ String* Class::ComputeName(Handle<Class> h_this) { if (name != nullptr) { return name; } - std::string descriptor(h_this->GetDescriptor()); + std::string temp; + const char* descriptor = h_this->GetDescriptor(&temp); Thread* self = Thread::Current(); if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { // The descriptor indicates that this is the class for @@ -186,12 +193,7 @@ String* Class::ComputeName(Handle<Class> h_this) { } else { // Convert the UTF-8 name to a java.lang.String. The name must use '.' to separate package // components. - if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') { - descriptor.erase(0, 1); - descriptor.erase(descriptor.size() - 1); - } - std::replace(descriptor.begin(), descriptor.end(), '/', '.'); - name = String::AllocFromModifiedUtf8(self, descriptor.c_str()); + name = String::AllocFromModifiedUtf8(self, DescriptorToDot(descriptor).c_str()); } h_this->SetName(name); return name; @@ -215,8 +217,9 @@ void Class::DumpClass(std::ostream& os, int flags) { Handle<mirror::Class> h_this(hs.NewHandle(this)); Handle<mirror::Class> h_super(hs.NewHandle(GetSuperClass())); + std::string temp; os << "----- " << (IsInterface() ? "interface" : "class") << " " - << "'" << GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n", + << "'" << GetDescriptor(&temp) << "' cl=" << GetClassLoader() << " -----\n", os << " objectSize=" << SizeOf() << " " << "(" << (h_super.Get() != nullptr ? h_super->SizeOf() : -1) << " from super)\n", os << StringPrintf(" access=0x%04x.%04x\n", @@ -336,7 +339,8 @@ bool Class::IsInSamePackage(Class* that) { return true; } // Compare the package part of the descriptor string. - return IsInSamePackage(klass1->GetDescriptor().c_str(), klass2->GetDescriptor().c_str()); + std::string temp1, temp2; + return IsInSamePackage(klass1->GetDescriptor(&temp1), klass2->GetDescriptor(&temp2)); } bool Class::IsStringClass() const { @@ -713,13 +717,14 @@ void Class::SetPreverifiedFlagOnAllMethods() { SetPreverifiedFlagOnMethods(GetVirtualMethods()); } -std::string Class::GetDescriptor() { - if (UNLIKELY(IsArrayClass())) { - return GetArrayDescriptor(); - } else if (UNLIKELY(IsPrimitive())) { +const char* Class::GetDescriptor(std::string* storage) { + if (IsPrimitive()) { return Primitive::Descriptor(GetPrimitiveType()); - } else if (UNLIKELY(IsProxyClass())) { - return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this); + } else if (IsArrayClass()) { + return GetArrayDescriptor(storage); + } else if (IsProxyClass()) { + *storage = Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this); + return storage->c_str(); } else { const DexFile& dex_file = GetDexFile(); const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_); @@ -727,8 +732,12 @@ std::string Class::GetDescriptor() { } } -std::string Class::GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return "[" + GetComponentType()->GetDescriptor(); +const char* Class::GetArrayDescriptor(std::string* storage) { + std::string temp; + const char* elem_desc = GetComponentType()->GetDescriptor(&temp); + *storage = "["; + *storage += elem_desc; + return storage->c_str(); } const DexFile::ClassDef* Class::GetClassDef() { @@ -791,7 +800,6 @@ mirror::Class* Class::GetDirectInterface(Thread* self, Handle<mirror::Class> kla } const char* Class::GetSourceFile() { - std::string descriptor(GetDescriptor()); const DexFile& dex_file = GetDexFile(); const DexFile::ClassDef* dex_class_def = GetClassDef(); if (dex_class_def == nullptr) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 2a3f1048bd..4b37beff34 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -965,11 +965,15 @@ class MANAGED Class FINAL : public Object { template<typename Visitor> void VisitEmbeddedImtAndVTable(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS; - std::string GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Get the descriptor of the class. In a few cases a std::string is required, rather than + // always create one the storage argument is populated and its internal c_str() returned. We do + // this to avoid memory allocation in the common case. + const char* GetDescriptor(std::string* storage) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + const char* GetArrayDescriptor(std::string* storage) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool DescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - std::string GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index da3c36cb06..aa181ee875 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -22,6 +22,7 @@ #include "array-inl.h" #include "art_field-inl.h" +#include "art_method-inl.h" #include "asm_support.h" #include "class-inl.h" #include "class_linker.h" @@ -31,11 +32,11 @@ #include "entrypoints/entrypoint_utils-inl.h" #include "gc/accounting/card_table-inl.h" #include "gc/heap.h" +#include "handle_scope-inl.h" #include "iftable-inl.h" -#include "art_method-inl.h" +#include "method_helper-inl.h" #include "object-inl.h" #include "object_array-inl.h" -#include "handle_scope-inl.h" #include "scoped_thread_state_change.h" #include "string-inl.h" |