summaryrefslogtreecommitdiffstats
path: root/runtime/mirror
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-08-12 02:30:58 -0700
committerIan Rogers <irogers@google.com>2014-08-12 16:08:05 -0700
commit1ff3c98775a4577cf053dba9a0c2d5c21c07b298 (patch)
tree2d09c27c69678b53b4c9dc486024f3547efd4bca /runtime/mirror
parent99c251bbd225dd97d0deece29559a430b12a0b66 (diff)
downloadart-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.h2
-rw-r--r--runtime/mirror/art_method.cc2
-rw-r--r--runtime/mirror/art_method.h4
-rw-r--r--runtime/mirror/class-inl.h6
-rw-r--r--runtime/mirror/class.cc50
-rw-r--r--runtime/mirror/class.h8
-rw-r--r--runtime/mirror/object_test.cc5
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"