summaryrefslogtreecommitdiffstats
path: root/runtime
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
parent99c251bbd225dd97d0deece29559a430b12a0b66 (diff)
downloadart-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.zip
art-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.tar.gz
art-1ff3c98775a4577cf053dba9a0c2d5c21c07b298.tar.bz2
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')
-rw-r--r--runtime/base/mutex-inl.h8
-rw-r--r--runtime/class_linker-inl.h4
-rw-r--r--runtime/class_linker.cc35
-rw-r--r--runtime/class_linker_test.cc39
-rw-r--r--runtime/common_throws.cc6
-rw-r--r--runtime/debugger.cc51
-rw-r--r--runtime/field_helper.cc12
-rw-r--r--runtime/gc/heap.cc3
-rw-r--r--runtime/interpreter/interpreter_common.cc14
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc8
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc8
-rw-r--r--runtime/jni_internal.cc13
-rw-r--r--runtime/leb128.h2
-rw-r--r--runtime/method_helper-inl.h17
-rw-r--r--runtime/method_helper.cc17
-rw-r--r--runtime/method_helper.h3
-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
-rw-r--r--runtime/native/java_lang_reflect_Array.cc3
-rw-r--r--runtime/proxy_test.cc5
-rw-r--r--runtime/reflection.cc15
-rw-r--r--runtime/utf-inl.h62
-rw-r--r--runtime/utf.h3
-rw-r--r--runtime/utils.cc42
-rw-r--r--runtime/utils.h8
-rw-r--r--runtime/verifier/method_verifier.cc39
-rw-r--r--runtime/verifier/reg_type.cc16
-rw-r--r--runtime/verifier/reg_type_cache.cc23
-rw-r--r--runtime/verifier/reg_type_cache.h8
34 files changed, 334 insertions, 207 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index 3e5cdba..f70db35 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -51,9 +51,11 @@ class ScopedContentionRecorder {
blocked_tid_(kLogLockContentions ? blocked_tid : 0),
owner_tid_(kLogLockContentions ? owner_tid : 0),
start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
- std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
- mutex->GetName(), owner_tid);
- ATRACE_BEGIN(msg.c_str());
+ if (ATRACE_ENABLED()) {
+ std::string msg = StringPrintf("Lock contention on %s (owner tid: %" PRIu64 ")",
+ mutex->GetName(), owner_tid);
+ ATRACE_BEGIN(msg.c_str());
+ }
}
~ScopedContentionRecorder() {
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 9921bdd..3af90b2 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -47,7 +47,9 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class**
}
}
DCHECK(!(*element_class)->IsPrimitiveVoid());
- std::string descriptor = "[" + (*element_class)->GetDescriptor();
+ std::string descriptor = "[";
+ std::string temp;
+ descriptor += (*element_class)->GetDescriptor(&temp);
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
HandleWrapper<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3b4976f..ee6fa66 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -40,7 +40,7 @@
#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "leb128.h"
-#include "method_helper.h"
+#include "method_helper-inl.h"
#include "oat.h"
#include "oat_file.h"
#include "object_lock.h"
@@ -97,7 +97,8 @@ static void ThrowEarlierClassFailure(mirror::Class* c)
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
if (c->GetVerifyErrorClass() != NULL) {
// TODO: change the verifier to store an _instance_, with a useful detail message?
- self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor().c_str(),
+ std::string temp;
+ self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor(&temp),
PrettyDescriptor(c).c_str());
} else {
self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
@@ -2482,17 +2483,18 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file
// Set finalizable flag on declaring class.
if (strcmp("V", dex_file.GetShorty(method_id.proto_idx_)) == 0) {
// Void return type.
- if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
+ if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged.
klass->SetFinalizable();
} else {
- std::string klass_descriptor = klass->GetDescriptor();
+ std::string temp;
+ const char* klass_descriptor = klass->GetDescriptor(&temp);
// The Enum class declares a "final" finalize() method to prevent subclasses from
// introducing a finalizer. We don't want to set the finalizable flag for Enum or its
// subclasses, so we exclude it here.
// We also want to avoid setting the flag on Object, where we know that finalize() is
// empty.
- if (klass_descriptor.compare("Ljava/lang/Object;") != 0 &&
- klass_descriptor.compare("Ljava/lang/Enum;") != 0) {
+ if (strcmp(klass_descriptor, "Ljava/lang/Object;") != 0 &&
+ strcmp(klass_descriptor, "Ljava/lang/Enum;") != 0) {
klass->SetFinalizable();
}
}
@@ -2991,6 +2993,7 @@ void ClassLinker::MoveImageClassesToClassTable() {
const char* old_no_suspend_cause =
self->StartAssertNoThreadSuspension("Moving image classes to class table");
mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches();
+ std::string temp;
for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
mirror::DexCache* dex_cache = dex_caches->Get(i);
mirror::ObjectArray<mirror::Class>* types = dex_cache->GetResolvedTypes();
@@ -2998,9 +3001,9 @@ void ClassLinker::MoveImageClassesToClassTable() {
mirror::Class* klass = types->Get(j);
if (klass != NULL) {
DCHECK(klass->GetClassLoader() == NULL);
- std::string descriptor = klass->GetDescriptor();
- size_t hash = Hash(descriptor.c_str());
- mirror::Class* existing = LookupClassFromTableLocked(descriptor.c_str(), NULL, hash);
+ const char* descriptor = klass->GetDescriptor(&temp);
+ size_t hash = Hash(descriptor);
+ mirror::Class* existing = LookupClassFromTableLocked(descriptor, NULL, hash);
if (existing != NULL) {
CHECK(existing == klass) << PrettyClassAndClassLoader(existing) << " != "
<< PrettyClassAndClassLoader(klass);
@@ -3265,9 +3268,10 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
// isn't a problem and this case shouldn't occur
return false;
}
+ std::string temp;
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
<< " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
- << klass->GetDescriptor();
+ << klass->GetDescriptor(&temp);
return false;
}
@@ -3786,7 +3790,8 @@ bool ClassLinker::InitializeClass(Handle<mirror::Class> klass, bool can_init_sta
// Set the class as initialized except if failed to initialize static fields.
klass->SetStatus(mirror::Class::kStatusInitialized, self);
if (VLOG_IS_ON(class_linker)) {
- LOG(INFO) << "Initialized class " << klass->GetDescriptor() << " from " <<
+ std::string temp;
+ LOG(INFO) << "Initialized class " << klass->GetDescriptor(&temp) << " from " <<
klass->GetLocation();
}
// Opportunistically set static method trampolines to their destination.
@@ -4301,9 +4306,10 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass,
interfaces->Get(i);
DCHECK(interface != NULL);
if (!interface->IsInterface()) {
+ std::string temp;
ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s",
PrettyDescriptor(klass.Get()).c_str(),
- PrettyDescriptor(interface->GetDescriptor()).c_str());
+ PrettyDescriptor(interface->GetDescriptor(&temp)).c_str());
return false;
}
// Check if interface is already in iftable
@@ -4677,11 +4683,12 @@ bool ClassLinker::LinkFields(Handle<mirror::Class> klass, bool is_static, size_t
} else {
klass->SetNumReferenceInstanceFields(num_reference_fields);
if (!klass->IsVariableSize()) {
- DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor();
+ std::string temp;
+ DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp);
size_t previous_size = klass->GetObjectSize();
if (previous_size != 0) {
// Make sure that we didn't originally have an incorrect size.
- CHECK_EQ(previous_size, size) << klass->GetDescriptor();
+ CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp);
}
klass->SetObjectSize(size);
}
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ class ClassLinkerTest : public CommonRuntimeTest {
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 @@ TEST_F(ClassLinkerTest, FindClass) {
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 @@ TEST_F(ClassLinkerTest, FindClass) {
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 @@ TEST_F(ClassLinkerTest, StaticFields) {
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, FinalizableBit) {
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;
}
}
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 970593d..bb48be3 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -296,8 +296,9 @@ void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
const StringPiece& type, const StringPiece& name)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::ostringstream msg;
+ std::string temp;
msg << "No " << scope << "field " << name << " of type " << type
- << " in class " << c->GetDescriptor() << " or its superclasses";
+ << " in class " << c->GetDescriptor(&temp) << " or its superclasses";
ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
}
@@ -306,8 +307,9 @@ void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
const Signature& signature) {
std::ostringstream msg;
+ std::string temp;
msg << "No " << type << " method " << name << signature
- << " in class " << c->GetDescriptor() << " or its super classes";
+ << " in class " << c->GetDescriptor(&temp) << " or its super classes";
ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index bc13379..fa1a1a8 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -451,6 +451,13 @@ static JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) {
return static_cast<JDWP::JdwpTag>(descriptor[0]);
}
+static JDWP::JdwpTag BasicTagFromClass(mirror::Class* klass)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ std::string temp;
+ const char* descriptor = klass->GetDescriptor(&temp);
+ return BasicTagFromDescriptor(descriptor);
+}
+
static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(c != NULL);
@@ -824,7 +831,8 @@ std::string Dbg::GetClassName(JDWP::RefTypeId class_id) {
if (!o->IsClass()) {
return StringPrintf("non-class %p", o); // This is only used for debugging output anyway.
}
- return DescriptorToName(o->AsClass()->GetDescriptor().c_str());
+ std::string temp;
+ return DescriptorToName(o->AsClass()->GetDescriptor(&temp));
}
JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) {
@@ -1140,7 +1148,8 @@ void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) {
Runtime::Current()->GetClassLinker()->VisitClasses(ClassListCreator::Visit, &clc);
}
-JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
+JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
+ uint32_t* pStatus, std::string* pDescriptor) {
JDWP::JdwpError status;
mirror::Class* c = DecodeClass(class_id, status);
if (c == NULL) {
@@ -1160,7 +1169,8 @@ JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* p
}
if (pDescriptor != NULL) {
- *pDescriptor = c->GetDescriptor();
+ std::string temp;
+ *pDescriptor = c->GetDescriptor(&temp);
}
return JDWP::ERR_NONE;
}
@@ -1196,7 +1206,8 @@ JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signatu
if (c == NULL) {
return status;
}
- *signature = c->GetDescriptor();
+ std::string temp;
+ *signature = c->GetDescriptor(&temp);
return JDWP::ERR_NONE;
}
@@ -1275,14 +1286,12 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- std::string descriptor(a->GetClass()->GetDescriptor());
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
-
- expandBufAdd1(pReply, tag);
+ JDWP::JdwpTag element_tag = BasicTagFromClass(a->GetClass()->GetComponentType());
+ expandBufAdd1(pReply, element_tag);
expandBufAdd4BE(pReply, count);
- if (IsPrimitiveTag(tag)) {
- size_t width = GetTagWidth(tag);
+ if (IsPrimitiveTag(element_tag)) {
+ size_t width = GetTagWidth(element_tag);
uint8_t* dst = expandBufAddSpace(pReply, count * width);
if (width == 8) {
const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0));
@@ -1303,7 +1312,7 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
for (int i = 0; i < count; ++i) {
mirror::Object* element = oa->Get(offset + i);
JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element)
- : tag;
+ : element_tag;
expandBufAdd1(pReply, specific_tag);
expandBufAddObjectId(pReply, gRegistry->Add(element));
}
@@ -1337,11 +1346,10 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- std::string descriptor = dst->GetClass()->GetDescriptor();
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
+ JDWP::JdwpTag element_tag = BasicTagFromClass(dst->GetClass()->GetComponentType());
- if (IsPrimitiveTag(tag)) {
- size_t width = GetTagWidth(tag);
+ if (IsPrimitiveTag(element_tag)) {
+ size_t width = GetTagWidth(element_tag);
if (width == 8) {
CopyArrayData<uint64_t>(dst, request, offset, count);
} else if (width == 4) {
@@ -2729,7 +2737,8 @@ void Dbg::PostClassPrepare(mirror::Class* c) {
// since the class may not yet be verified.
int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
JDWP::JdwpTypeTag tag = GetTypeTag(c);
- gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), c->GetDescriptor(), state);
+ std::string temp;
+ gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), c->GetDescriptor(&temp), state);
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
@@ -4518,7 +4527,8 @@ jbyteArray Dbg::GetRecentAllocations() {
int idx = HeadIndex();
while (count--) {
AllocRecord* record = &recent_allocation_records_[idx];
- class_names.Add(record->Type()->GetDescriptor());
+ std::string temp;
+ class_names.Add(record->Type()->GetDescriptor(&temp));
for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
mirror::ArtMethod* m = record->StackElement(i)->Method();
if (m != NULL) {
@@ -4559,9 +4569,9 @@ jbyteArray Dbg::GetRecentAllocations() {
JDWP::Append2BE(bytes, method_names.Size());
JDWP::Append2BE(bytes, filenames.Size());
- count = alloc_record_count_;
idx = HeadIndex();
- while (count--) {
+ std::string temp;
+ for (count = alloc_record_count_; count != 0; --count) {
// For each entry:
// (4b) total allocation size
// (2b) thread id
@@ -4570,7 +4580,7 @@ jbyteArray Dbg::GetRecentAllocations() {
AllocRecord* record = &recent_allocation_records_[idx];
size_t stack_depth = record->GetDepth();
size_t allocated_object_class_name_index =
- class_names.IndexOf(record->Type()->GetDescriptor().c_str());
+ class_names.IndexOf(record->Type()->GetDescriptor(&temp));
JDWP::Append4BE(bytes, record->ByteCount());
JDWP::Append2BE(bytes, record->ThinLockId());
JDWP::Append2BE(bytes, allocated_object_class_name_index);
@@ -4591,7 +4601,6 @@ jbyteArray Dbg::GetRecentAllocations() {
JDWP::Append2BE(bytes, file_name_index);
JDWP::Append2BE(bytes, record->StackElement(stack_frame)->LineNumber());
}
-
idx = (idx + 1) & (alloc_record_max_ - 1);
}
diff --git a/runtime/field_helper.cc b/runtime/field_helper.cc
index 40daa6d..5c85c46 100644
--- a/runtime/field_helper.cc
+++ b/runtime/field_helper.cc
@@ -41,17 +41,7 @@ mirror::Class* FieldHelper::GetType(bool resolve) {
}
const char* FieldHelper::GetDeclaringClassDescriptor() {
- uint32_t field_index = field_->GetDexFieldIndex();
- if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
- DCHECK(field_->IsStatic());
- DCHECK_LT(field_index, 2U);
- // 0 == Class[] interfaces; 1 == Class[][] throws;
- declaring_class_descriptor_ = field_->GetDeclaringClass()->GetDescriptor();
- return declaring_class_descriptor_.c_str();
- }
- const DexFile* dex_file = field_->GetDexFile();
- const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
- return dex_file->GetFieldDeclaringClassDescriptor(field_id);
+ return field_->GetDeclaringClass()->GetDescriptor(&declaring_class_descriptor_);
}
} // namespace art
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index cfaa170..5d138d2 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3092,8 +3092,7 @@ void Heap::AddModUnionTable(accounting::ModUnionTable* mod_union_table) {
void Heap::CheckPreconditionsForAllocObject(mirror::Class* c, size_t byte_count) {
CHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
- (c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
- c->GetDescriptor().empty());
+ (c->IsVariableSize() || c->GetObjectSize() == byte_count));
CHECK_GE(byte_count, sizeof(mirror::Object));
}
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index b35da0c..6705695 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -270,12 +270,13 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction
}
if (!reg->VerifierInstanceOf(field_class)) {
// This should never happen.
+ std::string temp1, temp2, temp3;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Put '%s' that is not instance of field '%s' in '%s'",
- reg->GetClass()->GetDescriptor().c_str(),
- field_class->GetDescriptor().c_str(),
- f->GetDeclaringClass()->GetDescriptor().c_str());
+ reg->GetClass()->GetDescriptor(&temp1),
+ field_class->GetDescriptor(&temp2),
+ f->GetDeclaringClass()->GetDescriptor(&temp3));
return false;
}
}
@@ -588,12 +589,13 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
}
if (!o->VerifierInstanceOf(arg_type)) {
// This should never happen.
+ std::string temp1, temp2;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Invoking %s with bad arg %d, type '%s' not instance of '%s'",
method->GetName(), shorty_pos,
- o->GetClass()->GetDescriptor().c_str(),
- arg_type->GetDescriptor().c_str());
+ o->GetClass()->GetDescriptor(&temp1),
+ arg_type->GetDescriptor(&temp2));
return false;
}
}
@@ -775,7 +777,7 @@ static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> class
if (found == nullptr && abort_if_not_found) {
if (!self->IsExceptionPending()) {
AbortTransaction(self, "%s failed in un-started runtime for class: %s",
- method_name.c_str(), PrettyDescriptor(descriptor).c_str());
+ method_name.c_str(), PrettyDescriptor(descriptor.c_str()).c_str());
}
return;
}
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index abd4b44..e098ac8 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -341,11 +341,12 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
}
if (!obj_result->VerifierInstanceOf(return_type)) {
// This should never happen.
+ std::string temp1, temp2;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- obj_result->GetClass()->GetDescriptor().c_str(),
- return_type->GetDescriptor().c_str());
+ obj_result->GetClass()->GetDescriptor(&temp1),
+ return_type->GetDescriptor(&temp2));
HANDLE_PENDING_EXCEPTION();
}
}
@@ -615,10 +616,11 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
ThrowNullPointerException(NULL, "throw with null exception");
} else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
// This should never happen.
+ std::string temp;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- exception->GetClass()->GetDescriptor().c_str());
+ exception->GetClass()->GetDescriptor(&temp));
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index c635648..5401495 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -256,11 +256,12 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
}
if (!obj_result->VerifierInstanceOf(return_type)) {
// This should never happen.
+ std::string temp1, temp2;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- obj_result->GetClass()->GetDescriptor().c_str(),
- return_type->GetDescriptor().c_str());
+ obj_result->GetClass()->GetDescriptor(&temp1),
+ return_type->GetDescriptor(&temp2));
HANDLE_PENDING_EXCEPTION();
}
}
@@ -529,10 +530,11 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
ThrowNullPointerException(NULL, "throw with null exception");
} else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
// This should never happen.
+ std::string temp;
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- exception->GetClass()->GetDescriptor().c_str());
+ exception->GetClass()->GetDescriptor(&temp));
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index d5e92a4..b7d485e 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -84,9 +84,10 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, mirror::Class* c,
const char* name, const char* sig, const char* kind)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+ std::string temp;
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchMethodError;",
"no %s method \"%s.%s%s\"",
- kind, c->GetDescriptor().c_str(), name, sig);
+ kind, c->GetDescriptor(&temp), name, sig);
}
static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, mirror::Class* c,
@@ -193,24 +194,26 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Throwable> cause(hs.NewHandle(soa.Self()->GetException(&throw_location)));
soa.Self()->ClearException();
+ std::string temp;
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" "
"could be found in class \"%s\" or its superclasses", sig, name,
- c->GetDescriptor().c_str());
+ c->GetDescriptor(&temp));
soa.Self()->GetException(nullptr)->SetCause(cause.Get());
return nullptr;
}
+ std::string temp;
if (is_static) {
field = mirror::Class::FindStaticField(soa.Self(), c, name,
- field_type->GetDescriptor().c_str());
+ field_type->GetDescriptor(&temp));
} else {
- field = c->FindInstanceField(name, field_type->GetDescriptor().c_str());
+ field = c->FindInstanceField(name, field_type->GetDescriptor(&temp));
}
if (field == nullptr) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no \"%s\" field \"%s\" in class \"%s\" or its superclasses",
- sig, name, c->GetDescriptor().c_str());
+ sig, name, c->GetDescriptor(&temp));
return nullptr;
}
return soa.EncodeField(field);
diff --git a/runtime/leb128.h b/runtime/leb128.h
index 0e80fe2..89de16e 100644
--- a/runtime/leb128.h
+++ b/runtime/leb128.h
@@ -28,7 +28,7 @@ namespace art {
static inline uint32_t DecodeUnsignedLeb128(const uint8_t** data) {
const uint8_t* ptr = *data;
int result = *(ptr++);
- if (result > 0x7f) {
+ if (UNLIKELY(result > 0x7f)) {
int cur = *(ptr++);
result = (result & 0x7f) | ((cur & 0x7f) << 7);
if (cur > 0x7f) {
diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h
index 3a5056a..9af835f 100644
--- a/runtime/method_helper-inl.h
+++ b/runtime/method_helper-inl.h
@@ -26,6 +26,23 @@
namespace art {
+inline bool MethodHelper::HasSameNameAndSignature(MethodHelper* other) {
+ const DexFile* dex_file = method_->GetDexFile();
+ const DexFile::MethodId& mid = dex_file->GetMethodId(GetMethod()->GetDexMethodIndex());
+ if (method_->GetDexCache() == other->method_->GetDexCache()) {
+ const DexFile::MethodId& other_mid =
+ dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
+ return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
+ }
+ const DexFile* other_dex_file = other->method_->GetDexFile();
+ const DexFile::MethodId& other_mid =
+ other_dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
+ if (!DexFileStringEquals(dex_file, mid.name_idx_, other_dex_file, other_mid.name_idx_)) {
+ return false; // Name mismatch.
+ }
+ return dex_file->GetMethodSignature(mid) == other_dex_file->GetMethodSignature(other_mid);
+}
+
inline mirror::Class* MethodHelper::GetClassFromTypeIdx(uint16_t type_idx, bool resolve) {
mirror::ArtMethod* method = GetMethod();
mirror::Class* type = method->GetDexCacheResolvedType(type_idx);
diff --git a/runtime/method_helper.cc b/runtime/method_helper.cc
index 1bd2f90..d6f83a8 100644
--- a/runtime/method_helper.cc
+++ b/runtime/method_helper.cc
@@ -36,23 +36,6 @@ mirror::String* MethodHelper::GetNameAsString(Thread* self) {
dex_cache);
}
-bool MethodHelper::HasSameNameAndSignature(MethodHelper* other) {
- const DexFile* dex_file = method_->GetDexFile();
- const DexFile::MethodId& mid = dex_file->GetMethodId(GetMethod()->GetDexMethodIndex());
- if (method_->GetDexCache() == other->method_->GetDexCache()) {
- const DexFile::MethodId& other_mid =
- dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
- return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
- }
- const DexFile* other_dex_file = other->method_->GetDexFile();
- const DexFile::MethodId& other_mid =
- other_dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
- if (!DexFileStringEquals(dex_file, mid.name_idx_, other_dex_file, other_mid.name_idx_)) {
- return false; // Name mismatch.
- }
- return dex_file->GetMethodSignature(mid) == other_dex_file->GetMethodSignature(other_mid);
-}
-
bool MethodHelper::HasSameSignatureWithDifferentClassLoaders(MethodHelper* other) {
if (UNLIKELY(GetReturnType() != other->GetReturnType())) {
return false;
diff --git a/runtime/method_helper.h b/runtime/method_helper.h
index 62465be..f71d273 100644
--- a/runtime/method_helper.h
+++ b/runtime/method_helper.h
@@ -105,7 +105,8 @@ class MethodHelper {
return GetParamPrimitiveType(param) == Primitive::kPrimNot;
}
- bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ALWAYS_INLINE bool HasSameNameAndSignature(MethodHelper* other)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 0dd1588..06700e6 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 8eacb1c..e88a390 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 4ebceff..fa592c2 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 c3754d7..b0ff7ea 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 f29ba73..5b8eb82 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 2a3f104..4b37bef 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 da3c36c..aa181ee 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"
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index f94e42b..058458f 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -34,7 +34,8 @@ static jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementCla
DCHECK(javaDimArray != NULL);
mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
- DCHECK_STREQ(dimensions_obj->GetClass()->GetDescriptor().c_str(), "[I");
+ DCHECK_EQ(dimensions_obj->GetClass()->GetComponentType()->GetPrimitiveType(),
+ Primitive::kPrimInt);
Handle<mirror::IntArray> dimensions_array(
hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj)));
mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class,
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 3081421..5af26b0 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -139,8 +139,9 @@ TEST_F(ProxyTest, ProxyClassHelper) {
EXPECT_EQ(2U, proxy_class->NumDirectInterfaces()); // Interfaces$I and Interfaces$J.
EXPECT_EQ(I.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 0));
EXPECT_EQ(J.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 1));
- std::string proxy_class_descriptor(proxy_class->GetDescriptor());
- EXPECT_STREQ("L$Proxy1234;", proxy_class_descriptor.c_str());
+ std::string temp;
+ const char* proxy_class_descriptor = proxy_class->GetDescriptor(&temp);
+ EXPECT_STREQ("L$Proxy1234;", proxy_class_descriptor);
EXPECT_EQ(nullptr, proxy_class->GetSourceFile());
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 0169ccc..cc50961 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -211,11 +211,11 @@ class ArgArray {
}
static void ThrowIllegalPrimitiveArgumentException(const char* expected,
- const StringPiece& found_descriptor)
+ const char* found_descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ThrowIllegalArgumentException(nullptr,
StringPrintf("Invalid primitive conversion from %s to %s", expected,
- PrettyDescriptor(found_descriptor.as_string()).c_str()).c_str());
+ PrettyDescriptor(found_descriptor).c_str()).c_str());
}
bool BuildArgArrayFromObjectArray(const ScopedObjectAccessAlreadyRunnable& soa,
@@ -257,8 +257,9 @@ class ArgArray {
#define DO_FAIL(expected) \
} else { \
if (arg->GetClass<>()->IsPrimitive()) { \
+ std::string temp; \
ThrowIllegalPrimitiveArgumentException(expected, \
- arg->GetClass<>()->GetDescriptor().c_str()); \
+ arg->GetClass<>()->GetDescriptor(&temp)); \
} else { \
ThrowIllegalArgumentException(nullptr, \
StringPrintf("method %s argument %zd has type %s, got %s", \
@@ -815,11 +816,11 @@ static bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object*
src_class = class_linker->FindPrimitiveClass('S');
boxed_value.SetS(primitive_field->GetShort(o));
} else {
+ std::string temp;
ThrowIllegalArgumentException(throw_location,
- StringPrintf("%s has type %s, got %s",
- UnboxingFailureKind(f).c_str(),
- PrettyDescriptor(dst_class).c_str(),
- PrettyDescriptor(o->GetClass()->GetDescriptor()).c_str()).c_str());
+ StringPrintf("%s has type %s, got %s", UnboxingFailureKind(f).c_str(),
+ PrettyDescriptor(dst_class).c_str(),
+ PrettyDescriptor(o->GetClass()->GetDescriptor(&temp)).c_str()).c_str());
return false;
}
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 uint16_t GetUtf16FromUtf8(const char** utf8_data_in) {
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
diff --git a/runtime/utf.h b/runtime/utf.h
index 29f8499..63cdbdc 100644
--- a/runtime/utf.h
+++ b/runtime/utf.h
@@ -55,7 +55,8 @@ void ConvertModifiedUtf8ToUtf16(uint16_t* utf16_out, const char* utf8_in);
/*
* Compare two modified UTF-8 strings as UTF-16 code point values in a non-locale sensitive manner
*/
-int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2);
+ALWAYS_INLINE int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1,
+ const char* utf8_2);
/*
* Compare a modified UTF-8 string with a UTF-16 string as code point values in a non-locale
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 @@ std::string PrettyDescriptor(mirror::String* java_descriptor) {
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 @@ std::string PrettyDescriptor(const std::string& descriptor) {
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 @@ std::string PrettyArguments(const char* signature) {
} 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 @@ std::string PrettyTypeOf(mirror::Object* obj) {
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 DotToDescriptor(const char* class_name) {
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;
}
diff --git a/runtime/utils.h b/runtime/utils.h
index f6773be..c89c41f 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -273,7 +273,7 @@ bool EndsWith(const std::string& s, const char* suffix);
// "java.lang.String[]", and so forth.
std::string PrettyDescriptor(mirror::String* descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-std::string PrettyDescriptor(const std::string& descriptor);
+std::string PrettyDescriptor(const char* descriptor);
std::string PrettyDescriptor(mirror::Class* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyDescriptor(Primitive::Type type);
@@ -335,10 +335,12 @@ std::string MangleForJni(const std::string& s);
// Turn "java.lang.String" into "Ljava/lang/String;".
std::string DotToDescriptor(const char* class_name);
-// Turn "Ljava/lang/String;" into "java.lang.String".
+// Turn "Ljava/lang/String;" into "java.lang.String" using the conventions of
+// java.lang.Class.getName().
std::string DescriptorToDot(const char* descriptor);
-// Turn "Ljava/lang/String;" into "java/lang/String".
+// Turn "Ljava/lang/String;" into "java/lang/String" using the opposite conventions of
+// java.lang.Class.getName().
std::string DescriptorToName(const char* descriptor);
// Tests for whether 's' is a valid class name in the three common forms:
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 329b4dc..fb57fc7 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -97,7 +97,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(mirror::Class* klass,
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* class_def = klass->GetClassDef();
mirror::Class* super = klass->GetSuperClass();
- if (super == NULL && "Ljava/lang/Object;" != klass->GetDescriptor()) {
+ std::string temp;
+ if (super == NULL && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
early_failure = true;
failure_message = " that has no super class";
} else if (super != NULL && super->IsFinal()) {
@@ -1457,10 +1458,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
*/
if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags()->IsInTry()) {
saved_line_->CopyFromLine(work_line_.get());
- } else {
-#ifndef NDEBUG
+ } else if (kIsDebugBuild) {
saved_line_->FillWithGarbage();
-#endif
}
@@ -2221,6 +2220,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
is_range, false);
const char* return_type_descriptor;
bool is_constructor;
+ RegType* return_type = nullptr;
if (called_method == NULL) {
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
@@ -2230,6 +2230,19 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
} else {
is_constructor = called_method->IsConstructor();
return_type_descriptor = called_method->GetReturnTypeDescriptor();
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
+ MethodHelper mh(h_called_method);
+ mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_);
+ if (return_type_class != nullptr) {
+ return_type = &reg_types_.FromClass(return_type_descriptor,
+ return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
+ } else {
+ DCHECK(!can_load_classes_ || self->IsExceptionPending());
+ self->ClearException();
+ }
}
if (is_constructor) {
/*
@@ -2271,12 +2284,14 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
*/
work_line_->MarkRefsAsInitialized(this_type);
}
- RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(),
- return_type_descriptor, false);
- if (!return_type.IsLowHalf()) {
- work_line_->SetResultRegisterType(return_type);
+ if (return_type == nullptr) {
+ return_type = &reg_types_.FromDescriptor(class_loader_->Get(),
+ return_type_descriptor, false);
+ }
+ if (!return_type->IsLowHalf()) {
+ work_line_->SetResultRegisterType(*return_type);
} else {
- work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
+ work_line_->SetResultRegisterTypeWide(*return_type, return_type->HighHalf(&reg_types_));
}
just_set_result = true;
break;
@@ -3121,7 +3136,8 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(T* it, const
RegType* res_method_class;
if (res_method != nullptr) {
mirror::Class* klass = res_method->GetDeclaringClass();
- res_method_class = &reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
+ std::string temp;
+ res_method_class = &reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
} else {
const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
@@ -3337,8 +3353,9 @@ mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instructio
}
if (!actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
+ std::string temp;
RegType& res_method_class =
- reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
+ reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 6422cdf..30be82f 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -414,20 +414,22 @@ std::string UnresolvedSuperClass::Dump() {
std::string UnresolvedReferenceType::Dump() {
std::stringstream result;
- result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor());
+ result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str());
return result.str();
}
std::string UnresolvedUninitializedRefType::Dump() {
std::stringstream result;
- result << "Unresolved And Uninitialized Reference" << ": " << PrettyDescriptor(GetDescriptor());
- result << " Allocation PC: " << GetAllocationPc();
+ result << "Unresolved And Uninitialized Reference" << ": "
+ << PrettyDescriptor(GetDescriptor().c_str())
+ << " Allocation PC: " << GetAllocationPc();
return result.str();
}
std::string UnresolvedUninitializedThisRefType::Dump() {
std::stringstream result;
- result << "Unresolved And Uninitialized This Reference" << PrettyDescriptor(GetDescriptor());
+ result << "Unresolved And Uninitialized This Reference"
+ << PrettyDescriptor(GetDescriptor().c_str());
return result.str();
}
@@ -618,7 +620,8 @@ RegType& RegType::GetSuperClass(RegTypeCache* cache) {
if (super_klass != NULL) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
- return cache->FromClass(super_klass->GetDescriptor().c_str(), super_klass, false);
+ std::string temp;
+ return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
} else {
return cache->Zero();
}
@@ -896,7 +899,8 @@ RegType& RegType::Merge(RegType& incoming_type, RegTypeCache* reg_types) {
} else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
- return reg_types->FromClass(join_class->GetDescriptor().c_str(), join_class, false);
+ std::string temp;
+ return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
}
}
} else {
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index c0e4351..482bb4d 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -122,9 +122,9 @@ RegType& RegTypeCache::RegTypeFromPrimitiveType(Primitive::Type prim_type) const
}
}
-bool RegTypeCache::MatchDescriptor(size_t idx, const char* descriptor, bool precise) {
+bool RegTypeCache::MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise) {
RegType* entry = entries_[idx];
- if (entry->descriptor_ != descriptor) {
+ if (descriptor != entry->descriptor_) {
return false;
}
if (entry->HasClass()) {
@@ -158,9 +158,11 @@ mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassL
RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
bool precise) {
- // Try looking up the class in the cache first.
+ // Try looking up the class in the cache first. We use a StringPiece to avoid continual strlen
+ // operations on the descriptor.
+ StringPiece descriptor_sp(descriptor);
for (size_t i = primitive_count_; i < entries_.size(); i++) {
- if (MatchDescriptor(i, descriptor, precise)) {
+ if (MatchDescriptor(i, descriptor_sp, precise)) {
return *(entries_[i]);
}
}
@@ -181,9 +183,9 @@ RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
if (klass->CannotBeAssignedFromOtherTypes() || precise) {
DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
DCHECK(!klass->IsInterface());
- entry = new PreciseReferenceType(klass, descriptor, entries_.size());
+ entry = new PreciseReferenceType(klass, descriptor_sp.as_string(), entries_.size());
} else {
- entry = new ReferenceType(klass, descriptor, entries_.size());
+ entry = new ReferenceType(klass, descriptor_sp.as_string(), entries_.size());
}
AddEntry(entry);
return *entry;
@@ -197,7 +199,7 @@ RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
DCHECK(!Thread::Current()->IsExceptionPending());
}
if (IsValidDescriptor(descriptor)) {
- RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
+ RegType* entry = new UnresolvedReferenceType(descriptor_sp.as_string(), entries_.size());
AddEntry(entry);
return *entry;
} else {
@@ -407,7 +409,7 @@ RegType& RegTypeCache::FromUninitialized(RegType& uninit_type) {
return *cur_entry;
}
}
- entry = new UnresolvedReferenceType(descriptor.c_str(), entries_.size());
+ entry = new UnresolvedReferenceType(descriptor, entries_.size());
} else {
mirror::Class* klass = uninit_type.GetClass();
if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
@@ -564,13 +566,14 @@ RegType& RegTypeCache::GetComponentType(RegType& array, mirror::ClassLoader* loa
return FromDescriptor(loader, component.c_str(), false);
} else {
mirror::Class* klass = array.GetClass()->GetComponentType();
+ std::string temp;
if (klass->IsErroneous()) {
// Arrays may have erroneous component types, use unresolved in that case.
// We assume that the primitive classes are not erroneous, so we know it is a
// reference type.
- return FromDescriptor(loader, klass->GetDescriptor().c_str(), false);
+ return FromDescriptor(loader, klass->GetDescriptor(&temp), false);
} else {
- return FromClass(klass->GetDescriptor().c_str(), klass,
+ return FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
}
}
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index d46cf2c..c0427eb 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -29,9 +29,11 @@
namespace art {
namespace mirror {
-class Class;
-class ClassLoader;
+ class Class;
+ class ClassLoader;
} // namespace mirror
+class StringPiece;
+
namespace verifier {
class RegType;
@@ -149,7 +151,7 @@ class RegTypeCache {
void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool MatchDescriptor(size_t idx, const char* descriptor, bool precise)
+ bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);