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 | |
parent | 99c251bbd225dd97d0deece29559a430b12a0b66 (diff) | |
download | art-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')
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 = ®_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 = ®_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(®_types_)); + work_line_->SetResultRegisterTypeWide(*return_type, return_type->HighHalf(®_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 = ®_types_.FromClass(klass->GetDescriptor().c_str(), klass, + std::string temp; + res_method_class = ®_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_); |