diff options
author | Ian Rogers <irogers@google.com> | 2013-09-23 23:51:32 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-09-24 17:07:24 -0700 |
commit | fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f (patch) | |
tree | 5cfbe05084351576e9659cb8f7b66dcb6163a37b | |
parent | 576fe9d4181c749aa510e32d2521ed4192bdfda0 (diff) | |
download | art-fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f.zip art-fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f.tar.gz art-fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f.tar.bz2 |
StringPiece clean up.
Profile guided clean up.
Try to avoid creating StringPieces with the contents of a dex file where
the length is known.
Try to avoid RegTypeCache::FromDescriptor when there's a class available.
Make ConstantType::ConstantValue inlinable.
Saving of about 50ms from a 2 threaded ThinkFree compile on host.
Change-Id: I47a12c3c76f46e2c9805be1c3a3e3870fe1f5d85
-rw-r--r-- | compiler/dex/quick/gen_invoke.cc | 4 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 27 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 2 | ||||
-rw-r--r-- | compiler/image_writer.cc | 4 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 2 | ||||
-rw-r--r-- | runtime/class_linker.cc | 107 | ||||
-rw-r--r-- | runtime/debugger.cc | 13 | ||||
-rw-r--r-- | runtime/debugger.h | 2 | ||||
-rw-r--r-- | runtime/dex_file-inl.h | 11 | ||||
-rw-r--r-- | runtime/dex_file.h | 3 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 2 | ||||
-rw-r--r-- | runtime/interpreter/interpreter.cc | 2 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_handler.cc | 4 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 14 | ||||
-rw-r--r-- | runtime/object_utils.h | 167 | ||||
-rw-r--r-- | runtime/reflection.cc | 4 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 155 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 1 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 5 | ||||
-rw-r--r-- | runtime/verifier/reg_type.h | 9 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.cc | 1 |
21 files changed, 350 insertions, 189 deletions
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 72ae91e..ed83863 100644 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -1219,8 +1219,10 @@ bool Mir2Lir::GenIntrinsic(CallInfo* info) { * method. By doing this during basic block construction, we can also * take advantage of/generate new useful dataflow info. */ + const DexFile::MethodId& target_mid = cu_->dex_file->GetMethodId(info->index); + const DexFile::TypeId& declaring_type = cu_->dex_file->GetTypeId(target_mid.class_idx_); StringPiece tgt_methods_declaring_class( - cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index))); + cu_->dex_file->StringDataAsStringPieceByIdx(declaring_type.descriptor_idx_)); if (tgt_methods_declaring_class.starts_with("Ljava/lang/Double;")) { std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file)); if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") { diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index c12a7d9..e227715 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -600,12 +600,11 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De UpdateImageClasses(timings); } -bool CompilerDriver::IsImageClass(const char* descriptor) const { - DCHECK(descriptor != NULL); +bool CompilerDriver::IsImageClass(const StringPiece& descriptor) const { if (!IsImage()) { return true; } else { - return image_classes_->find(descriptor) != image_classes_->end(); + return image_classes_->find(descriptor.data()) != image_classes_->end(); } } @@ -780,7 +779,8 @@ void CompilerDriver::UpdateImageClasses(base::TimingLogger& timings) { bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) { - if (IsImage() && IsImageClass(dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx)))) { + if (IsImage() && + IsImageClass(dex_file.StringDataAsStringPieceByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) { if (kIsDebugBuild) { ScopedObjectAccess soa(Thread::Current()); mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); @@ -1098,7 +1098,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType s if (compiling_boot) { if (support_boot_image_fixup_) { MethodHelper mh(method); - if (IsImageClass(mh.GetDeclaringClassDescriptor())) { + if (IsImageClass(mh.GetDeclaringClassDescriptorAsStringPiece())) { // We can only branch directly to Methods that are resolved in the DexCache. // Otherwise we won't invoke the resolution trampoline. *direct_method = -1; @@ -1572,8 +1572,8 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i CHECK(soa.Self()->IsExceptionPending()); mirror::Throwable* exception = soa.Self()->GetException(NULL); VLOG(compiler) << "Exception during type resolution: " << exception->Dump(); - if (strcmp(ClassHelper(exception->GetClass()).GetDescriptor(), - "Ljava/lang/OutOfMemoryError;") == 0) { + if (ClassHelper(exception->GetClass()).GetDescriptorAsStringPiece() == + "Ljava/lang/OutOfMemoryError;") { // There's little point continuing compilation if the heap is exhausted. LOG(FATAL) << "Out of memory during type resolution for compilation"; } @@ -2084,11 +2084,14 @@ static const char* class_initializer_black_list[] = { static void InitializeClass(const ParallelCompilationManager* manager, size_t class_def_index) LOCKS_EXCLUDED(Locks::mutator_lock_) { ATRACE_CALL(); - const DexFile::ClassDef& class_def = manager->GetDexFile()->GetClassDef(class_def_index); + const DexFile* dex_file = manager->GetDexFile(); + const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); + const DexFile::TypeId& class_type_id = dex_file->GetTypeId(class_def.class_idx_); + StringPiece descriptor(dex_file->StringDataAsStringPieceByIdx(class_type_id.descriptor_idx_)); + ScopedObjectAccess soa(Thread::Current()); mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()); - const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def); - mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader); + mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor.data(), class_loader); if (klass != NULL) { // Only try to initialize classes that were successfully verified. if (klass->IsVerified()) { @@ -2118,7 +2121,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl bool is_black_listed = StringPiece(descriptor).ends_with("$NoPreloadHolder;"); if (!is_black_listed) { for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) { - if (StringPiece(descriptor) == class_initializer_black_list[i]) { + if (descriptor == class_initializer_black_list[i]) { is_black_listed = true; break; } @@ -2126,7 +2129,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl } if (!is_black_listed) { VLOG(compiler) << "Initializing: " << descriptor; - if (StringPiece(descriptor) == "Ljava/lang/Void;") { + if (descriptor == "Ljava/lang/Void;") { // Hand initialize j.l.Void to avoid Dex file operations in un-started runtime. ObjectLock lock(soa.Self(), klass); mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields(); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 66c9cbf..7657af5 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -309,7 +309,7 @@ class CompilerDriver { } // Checks if class specified by type_idx is one of the image_classes_ - bool IsImageClass(const char* descriptor) const; + bool IsImageClass(const StringPiece& descriptor) const; void RecordClassStatus(ClassReference ref, mirror::Class::Status status) LOCKS_EXCLUDED(compiled_classes_lock_); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index f82c6fb..bcdc1c1 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -241,7 +241,7 @@ void ImageWriter::ComputeEagerResolvedStrings() } bool ImageWriter::IsImageClass(const Class* klass) { - return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor()); + return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptorAsStringPiece()); } struct NonImageClasses { @@ -296,7 +296,7 @@ void ImageWriter::PruneNonImageClasses() { bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); if (!context->image_writer->IsImageClass(klass)) { - context->non_image_classes->insert(ClassHelper(klass).GetDescriptor()); + context->non_image_classes->insert(ClassHelper(klass).GetDescriptorAsStringPiece().as_string()); } return true; } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index fc9e00c..cc6b5d7 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1119,7 +1119,7 @@ class ImageDumper { typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable; SizeAndCountTable sizes_and_counts; - void Update(const std::string& descriptor, size_t object_bytes) { + void Update(const char* descriptor, size_t object_bytes) { SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor); if (it != sizes_and_counts.end()) { it->second.bytes += object_bytes; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 91db883..6aae63e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1840,7 +1840,7 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file SirtRef<mirror::Class>& klass) { uint32_t dex_method_idx = it.GetMemberIndex(); const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); - StringPiece method_name(dex_file.GetMethodName(method_id)); + StringPiece method_name(dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_)); mirror::ArtMethod* dst = AllocArtMethod(self); if (UNLIKELY(dst == NULL)) { @@ -1869,7 +1869,7 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file klass->SetFinalizable(); } else { ClassHelper kh(klass.get()); - StringPiece klass_descriptor(kh.GetDescriptor()); + StringPiece klass_descriptor(kh.GetDescriptorAsStringPiece()); // 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. @@ -2219,7 +2219,7 @@ bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader* ++it) { mirror::Class* klass = it->second; kh.ChangeClass(klass); - if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) { + if (kh.GetDescriptorAsStringPiece() == descriptor && klass->GetClassLoader() == class_loader) { class_table_.erase(it); return true; } @@ -2265,15 +2265,16 @@ mirror::Class* ClassLinker::LookupClassFromTableLocked(const char* descriptor, for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) { mirror::Class* klass = it->second; kh.ChangeClass(klass); - if (klass->GetClassLoader() == class_loader && strcmp(descriptor, kh.GetDescriptor()) == 0) { + if (klass->GetClassLoader() == class_loader && kh.GetDescriptorAsStringPiece() == descriptor) { if (kIsDebugBuild) { // Check for duplicates in the table. for (++it; it != end && it->first == hash; ++it) { mirror::Class* klass2 = it->second; kh.ChangeClass(klass2); - CHECK(!(strcmp(descriptor, kh.GetDescriptor()) == 0 && klass2->GetClassLoader() == class_loader)) - << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " " - << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader(); + CHECK(!(kh.GetDescriptorAsStringPiece() == descriptor && + klass2->GetClassLoader() == class_loader)) + << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " " + << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader(); } } return klass; @@ -2379,7 +2380,7 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Clas it != end && it->first == hash; ++it) { mirror::Class* klass = it->second; kh.ChangeClass(klass); - if (strcmp(descriptor, kh.GetDescriptor()) == 0) { + if (kh.GetDescriptorAsStringPiece() == descriptor) { result.push_back(klass); } } @@ -2538,11 +2539,11 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass); const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation()); CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass); - const char* descriptor = ClassHelper(klass).GetDescriptor(); uint16_t class_def_index = klass->GetDexClassDefIndex(); UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index)); CHECK(oat_class.get() != NULL) - << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor; + << dex_file.GetLocation() << " " << PrettyClass(klass) << " " + << ClassHelper(klass).GetDescriptor(); oat_file_class_status = oat_class->GetStatus(); if (oat_file_class_status == mirror::Class::kStatusVerified || oat_file_class_status == mirror::Class::kStatusInitialized) { @@ -2581,7 +2582,8 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class return false; } LOG(FATAL) << "Unexpected class status: " << oat_file_class_status - << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor; + << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " + << ClassHelper(klass).GetDescriptor(); return false; } @@ -3727,10 +3729,10 @@ struct LinkFieldsComparator { // same basic group? then sort by string. fh_->ChangeField(field1); - StringPiece name1(fh_->GetName()); + const char* name1 = fh_->GetName(); fh_->ChangeField(field2); - StringPiece name2(fh_->GetName()); - return name1 < name2; + const char* name2 = fh_->GetName(); + return strcmp(name1, name2) < 0; } FieldHelper* fh_; @@ -3764,7 +3766,9 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) { // minimizes disruption of C++ version such as Class and Method. std::deque<mirror::ArtField*> grouped_and_sorted_fields; for (size_t i = 0; i < num_fields; i++) { - grouped_and_sorted_fields.push_back(fields->Get(i)); + mirror::ArtField* f = fields->Get(i); + CHECK(f != NULL); + grouped_and_sorted_fields.push_back(f); } FieldHelper fh(NULL, this); std::sort(grouped_and_sorted_fields.begin(), @@ -3831,7 +3835,7 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) { // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it. if (!is_static && - StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;") { + (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;")) { // We know there are no non-reference fields in the Reference classes, and we know // that 'referent' is alphabetically last, so this is easy... CHECK_EQ(num_reference_fields, num_fields); @@ -3840,39 +3844,39 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) { --num_reference_fields; } -#ifndef NDEBUG - // Make sure that all reference fields appear before - // non-reference fields, and all double-wide fields are aligned. - bool seen_non_ref = false; - for (size_t i = 0; i < num_fields; i++) { - mirror::ArtField* field = fields->Get(i); - if (false) { // enable to debug field layout - LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance") - << " class=" << PrettyClass(klass.get()) - << " field=" << PrettyField(field) - << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()), - false); - } - fh.ChangeField(field); - Primitive::Type type = fh.GetTypeAsPrimitiveType(); - bool is_primitive = type != Primitive::kPrimNot; - if (StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;" && - StringPiece(fh.GetName()) == "referent") { - is_primitive = true; // We lied above, so we have to expect a lie here. - } - if (is_primitive) { - if (!seen_non_ref) { - seen_non_ref = true; - DCHECK_EQ(num_reference_fields, i); + if (kIsDebugBuild) { + // Make sure that all reference fields appear before + // non-reference fields, and all double-wide fields are aligned. + bool seen_non_ref = false; + for (size_t i = 0; i < num_fields; i++) { + mirror::ArtField* field = fields->Get(i); + if (false) { // enable to debug field layout + LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance") + << " class=" << PrettyClass(klass.get()) + << " field=" << PrettyField(field) + << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()), + false); + } + fh.ChangeField(field); + Primitive::Type type = fh.GetTypeAsPrimitiveType(); + bool is_primitive = type != Primitive::kPrimNot; + if (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;" && + fh.GetNameAsStringPiece() == "referent") { + is_primitive = true; // We lied above, so we have to expect a lie here. + } + if (is_primitive) { + if (!seen_non_ref) { + seen_non_ref = true; + DCHECK_EQ(num_reference_fields, i); + } + } else { + DCHECK(!seen_non_ref); } - } else { - DCHECK(!seen_non_ref); + } + if (!seen_non_ref) { + DCHECK_EQ(num_fields, num_reference_fields); } } - if (!seen_non_ref) { - DCHECK_EQ(num_fields, num_reference_fields); - } -#endif size = field_offset.Uint32Value(); // Update klass if (is_static) { @@ -4175,9 +4179,9 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, } mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, - uint32_t field_idx, - mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader) { + uint32_t field_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader) { DCHECK(dex_cache != NULL); mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx); if (resolved != NULL) { @@ -4190,8 +4194,9 @@ mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, return NULL; } - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); + StringPiece name(dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_)); + StringPiece type(dex_file.StringDataAsStringPieceByIdx( + dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_)); resolved = klass->FindField(name, type); if (resolved != NULL) { dex_cache->SetResolvedField(field_idx, resolved); diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 88269e5..2eca734 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -891,7 +891,7 @@ JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* p } if (pDescriptor != NULL) { - *pDescriptor = ClassHelper(c).GetDescriptor(); + *pDescriptor = ClassHelper(c).GetDescriptorAsStringPiece().as_string(); } return JDWP::ERR_NONE; } @@ -928,13 +928,13 @@ JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string& signature) { +JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) { JDWP::JdwpError status; mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } - signature = ClassHelper(c).GetDescriptor(); + *signature = ClassHelper(c).GetDescriptorAsStringPiece().as_string(); return JDWP::ERR_NONE; } @@ -1065,8 +1065,8 @@ 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(ClassHelper(dst->GetClass()).GetDescriptor()); - JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1); + const char* descriptor = ClassHelper(dst->GetClass()).GetDescriptor(); + JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1); if (IsPrimitiveTag(tag)) { size_t width = GetTagWidth(tag); @@ -2287,7 +2287,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 = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; - gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), ClassHelper(c).GetDescriptor(), state); + gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), + ClassHelper(c).GetDescriptorAsStringPiece().as_string(), state); } void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object, diff --git a/runtime/debugger.h b/runtime/debugger.h index d0fe445..8574a33 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -149,7 +149,7 @@ class Dbg { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string& signature) + static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h index dee8026..2ee9244 100644 --- a/runtime/dex_file-inl.h +++ b/runtime/dex_file-inl.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_DEX_FILE_INL_H_ #include "base/logging.h" +#include "base/stringpiece.h" #include "dex_file.h" #include "leb128.h" #include "utils.h" @@ -36,6 +37,16 @@ inline const char* DexFile::GetStringDataAndLength(const StringId& string_id, ui return reinterpret_cast<const char*>(ptr); } +inline StringPiece DexFile::StringDataAsStringPieceByIdx(uint32_t idx) const { + if (idx == kDexNoIndex) { + return StringPiece(); + } + const StringId& string_id = GetStringId(idx); + uint32_t length; + const char* data = GetStringDataAndLength(string_id, &length); + return StringPiece(data, static_cast<int>(length)); +} + inline const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) { const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_]; return reinterpret_cast<const TryItem*> diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 7be5cb8..4534b41 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -40,6 +40,7 @@ namespace mirror { class DexCache; } // namespace mirror class ClassLinker; +class StringPiece; class ZipArchive; // TODO: move all of the macro functionality into the DexCache class. @@ -432,6 +433,8 @@ class DexFile { return GetStringDataAndLength(string_id, unicode_length); } + StringPiece StringDataAsStringPieceByIdx(uint32_t idx) const; + const char* StringDataByIdx(uint32_t idx) const { uint32_t unicode_length; return StringDataAndLengthByIdx(idx, &unicode_length); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index ccd9aac..2ad6117 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -557,7 +557,7 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void* mirror::Object* Heap::AllocObject(Thread* self, mirror::Class* c, size_t byte_count) { DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) || (c->IsVariableSize() || c->GetObjectSize() == byte_count) || - strlen(ClassHelper(c).GetDescriptor()) == 0); + ClassHelper(c).GetDescriptorAsStringPiece().length() == 0); DCHECK_GE(byte_count, sizeof(mirror::Object)); mirror::Object* obj = NULL; diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index f35cfa3..fd92e06 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -82,7 +82,7 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method, } } -static void InterpreterJni(Thread* self, ArtMethod* method, StringPiece shorty, +static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty, Object* receiver, uint32_t* args, JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler, diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index a2efc48..523d892 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -47,7 +47,7 @@ std::string DescribeMethod(const MethodId& method_id) { std::string DescribeRefTypeId(const RefTypeId& ref_type_id) { std::string signature("unknown"); - Dbg::GetSignature(ref_type_id, signature); + Dbg::GetSignature(ref_type_id, &signature); return StringPrintf("%#llx (%s)", ref_type_id, signature.c_str()); } @@ -547,7 +547,7 @@ static JdwpError RT_Signature(JdwpState*, Request& request, ExpandBuf* pReply, b RefTypeId refTypeId = request.ReadRefTypeId(); std::string signature; - JdwpError status = Dbg::GetSignature(refTypeId, signature); + JdwpError status = Dbg::GetSignature(refTypeId, &signature); if (status != ERR_NONE) { return status; } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index c128ede..287e8b0 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -135,7 +135,7 @@ String* Class::ComputeName() { if (name != NULL) { return name; } - std::string descriptor(ClassHelper(this).GetDescriptor()); + std::string descriptor(ClassHelper(this).GetDescriptorAsStringPiece().as_string()); if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { // The descriptor indicates that this is the class for // a primitive type; special-case the return value. @@ -294,8 +294,8 @@ bool Class::IsInSamePackage(const Class* that) const { return true; } // Compare the package part of the descriptor string. - return IsInSamePackage(ClassHelper(klass1).GetDescriptor(), - ClassHelper(klass2).GetDescriptor()); + return IsInSamePackage(ClassHelper(klass1).GetDescriptorAsStringPiece(), + ClassHelper(klass2).GetDescriptorAsStringPiece()); } bool Class::IsClassClass() const { @@ -367,7 +367,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const String for (size_t i = 0; i < NumDirectMethods(); ++i) { ArtMethod* method = GetDirectMethod(i); mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { + if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) { return method; } } @@ -412,7 +412,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, for (size_t i = 0; i < NumVirtualMethods(); ++i) { ArtMethod* method = GetVirtualMethod(i); mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { + if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) { return method; } } @@ -458,7 +458,7 @@ ArtField* Class::FindDeclaredInstanceField(const StringPiece& name, const String for (size_t i = 0; i < NumInstanceFields(); ++i) { ArtField* f = GetInstanceField(i); fh.ChangeField(f); - if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { + if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) { return f; } } @@ -507,7 +507,7 @@ ArtField* Class::FindDeclaredStaticField(const StringPiece& name, const StringPi for (size_t i = 0; i < NumStaticFields(); ++i) { ArtField* f = GetStaticField(i); fh.ChangeField(f); - if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { + if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) { return f; } } diff --git a/runtime/object_utils.h b/runtime/object_utils.h index 6ee3016..9e107a4 100644 --- a/runtime/object_utils.h +++ b/runtime/object_utils.h @@ -111,6 +111,17 @@ class ClassHelper { } } + StringPiece GetDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + CHECK(klass_ != NULL); + if (UNLIKELY(klass_->IsArrayClass() || klass_->IsPrimitive() || klass_->IsProxyClass())) { + return StringPiece(GetDescriptor()); + } else { + const DexFile& dex_file = GetDexFile(); + const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_); + return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_); + } + } + const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string result("["); const mirror::Class* saved_klass = klass_; @@ -182,7 +193,7 @@ class ClassHelper { } const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - std::string descriptor(GetDescriptor()); + std::string descriptor(GetDescriptorAsStringPiece().as_string()); const DexFile& dex_file = GetDexFile(); const DexFile::ClassDef* dex_class_def = GetClassDef(); CHECK(dex_class_def != NULL); @@ -267,53 +278,77 @@ class FieldHelper { } field_ = new_f; } + const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); - if (!field_->GetDeclaringClass()->IsProxyClass()) { - const DexFile& dex_file = GetDexFile(); - return dex_file.GetFieldName(dex_file.GetFieldId(field_index)); - } else { + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { DCHECK(field_->IsStatic()); DCHECK_LT(field_index, 2U); return field_index == 0 ? "interfaces" : "throws"; } + const DexFile& dex_file = GetDexFile(); + return dex_file.GetFieldName(dex_file.GetFieldId(field_index)); } + + StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uint32_t field_index = field_->GetDexFieldIndex(); + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { + return StringPiece(GetName()); + } + const DexFile& dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); + return dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_); + } + mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); - if (!field_->GetDeclaringClass()->IsProxyClass()) { - const DexFile& dex_file = GetDexFile(); - const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); - mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_); - if (resolve && (type == NULL)) { - type = GetClassLinker()->ResolveType(field_id.type_idx_, field_); - CHECK(type != NULL || Thread::Current()->IsExceptionPending()); - } - return type; - } else { + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { return GetClassLinker()->FindSystemClass(GetTypeDescriptor()); } + const DexFile& dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); + mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_); + if (resolve && (type == NULL)) { + type = GetClassLinker()->ResolveType(field_id.type_idx_, field_); + CHECK(type != NULL || Thread::Current()->IsExceptionPending()); + } + return type; } + const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); - if (!field_->GetDeclaringClass()->IsProxyClass()) { - const DexFile& dex_file = GetDexFile(); - const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); - return dex_file.GetFieldTypeDescriptor(field_id); - } else { + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { DCHECK(field_->IsStatic()); DCHECK_LT(field_index, 2U); // 0 == Class[] interfaces; 1 == Class[][] throws; return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;"; } + const DexFile& dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); + return dex_file.GetFieldTypeDescriptor(field_id); + } + + StringPiece GetTypeDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uint32_t field_index = field_->GetDexFieldIndex(); + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { + return StringPiece(GetTypeDescriptor()); + } + const DexFile& dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); + const DexFile::TypeId& type_id = dex_file.GetTypeId(field_id.type_idx_); + return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_); } + Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return Primitive::GetType(GetTypeDescriptor()[0]); } + bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Primitive::Type type = GetTypeAsPrimitiveType(); return type != Primitive::kPrimNot; } + size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Primitive::Type type = GetTypeAsPrimitiveType(); return Primitive::FieldSize(type); @@ -324,18 +359,17 @@ class FieldHelper { const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); - if (!field_->GetDeclaringClass()->IsProxyClass()) { - const DexFile& dex_file = GetDexFile(); - const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); - return dex_file.GetFieldDeclaringClassDescriptor(field_id); - } else { + if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { DCHECK(field_->IsStatic()); DCHECK_LT(field_index, 2U); // 0 == Class[] interfaces; 1 == Class[][] throws; ClassHelper kh(field_->GetDeclaringClass()); - declaring_class_descriptor_ = kh.GetDescriptor(); + declaring_class_descriptor_ = kh.GetDescriptorAsStringPiece().as_string(); return declaring_class_descriptor_.c_str(); } + const DexFile& dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); + return dex_file.GetFieldDeclaringClassDescriptor(field_id); } private: @@ -417,7 +451,7 @@ class MethodHelper { const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile& dex_file = GetDexFile(); uint32_t dex_method_idx = method_->GetDexMethodIndex(); - if (dex_method_idx != DexFile::kDexNoIndex) { + if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx)); } else { Runtime* runtime = Runtime::Current(); @@ -435,6 +469,16 @@ class MethodHelper { } } + StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const DexFile& dex_file = GetDexFile(); + uint32_t dex_method_idx = method_->GetDexMethodIndex(); + if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { + return StringPiece(GetName()); + } + const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); + return dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_); + } + mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile& dex_file = GetDexFile(); uint32_t dex_method_idx = method_->GetDexMethodIndex(); @@ -508,11 +552,22 @@ class MethodHelper { const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile& dex_file = GetDexFile(); uint32_t dex_method_idx = method_->GetDexMethodIndex(); - if (dex_method_idx != DexFile::kDexNoIndex) { - return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx)); - } else { + if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { return "<runtime method>"; } + return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx)); + } + + StringPiece GetDeclaringClassDescriptorAsStringPiece() + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const DexFile& dex_file = GetDexFile(); + uint32_t dex_method_idx = method_->GetDexMethodIndex(); + if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { + return StringPiece("<runtime method>"); + } + const DexFile::MethodId& mid = dex_file.GetMethodId(dex_method_idx); + const DexFile::TypeId& type_id = dex_file.GetTypeId(mid.class_idx_); + return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_); } const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -536,7 +591,7 @@ class MethodHelper { } bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return IsStatic() && StringPiece(GetName()) == "<clinit>"; + return IsStatic() && GetNameAsStringPiece() == "<clinit>"; } size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -569,16 +624,56 @@ class MethodHelper { bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const DexFile& dex_file = GetDexFile(); + const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex()); if (GetDexCache() == other->GetDexCache()) { - const DexFile& dex_file = GetDexFile(); - const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex()); const DexFile::MethodId& other_mid = dex_file.GetMethodId(other->method_->GetDexMethodIndex()); return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_; } - StringPiece name(GetName()); - StringPiece other_name(other->GetName()); - return name == other_name && GetSignature() == other->GetSignature(); + const DexFile& other_dex_file = other->GetDexFile(); + const DexFile::MethodId& other_mid = + other_dex_file.GetMethodId(other->method_->GetDexMethodIndex()); + if (dex_file.StringDataAsStringPieceByIdx(mid.name_idx_) != + other_dex_file.StringDataAsStringPieceByIdx(other_mid.name_idx_)) { + return false; // Name mismatch. + } + const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(mid); + const DexFile::ProtoId& other_proto_id = other_dex_file.GetMethodPrototype(other_mid); + if (dex_file.StringDataAsStringPieceByIdx(proto_id.shorty_idx_) != + other_dex_file.StringDataAsStringPieceByIdx(other_proto_id.shorty_idx_)) { + return false; // Shorty mismatch. + } + const DexFile::TypeId& return_type_id = dex_file.GetTypeId(proto_id.return_type_idx_); + const DexFile::TypeId& other_return_type_id = + other_dex_file.GetTypeId(other_proto_id.return_type_idx_); + if (dex_file.StringDataAsStringPieceByIdx(return_type_id.descriptor_idx_) != + other_dex_file.StringDataAsStringPieceByIdx(other_return_type_id.descriptor_idx_)) { + return false; // Return type mismatch. + } + const DexFile::TypeList* params = dex_file.GetProtoParameters(proto_id); + const DexFile::TypeList* other_params = other_dex_file.GetProtoParameters(other_proto_id); + if (params == nullptr) { + return other_params == nullptr; // Check both lists are empty. + } + if (other_params == nullptr) { + return false; // Parameter list size mismatch. + } + uint32_t params_size = params->Size(); + uint32_t other_params_size = other_params->Size(); + if (params_size != other_params_size) { + return false; // Parameter list size mismatch. + } + for (uint32_t i = 0; i < params_size; ++i) { + const DexFile::TypeId& param_id = dex_file.GetTypeId(params->GetTypeItem(i).type_idx_); + const DexFile::TypeId& other_param_id = + other_dex_file.GetTypeId(other_params->GetTypeItem(i).type_idx_); + if (dex_file.StringDataAsStringPieceByIdx(param_id.descriptor_idx_) != + other_dex_file.StringDataAsStringPieceByIdx(other_param_id.descriptor_idx_)) { + return false; // Parameter type mismatch. + } + } + return true; } const DexFile::CodeItem* GetCodeItem() diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 3e58b4b..4ff7349 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -323,7 +323,7 @@ static bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object* } JValue boxed_value; - std::string src_descriptor(ClassHelper(o->GetClass()).GetDescriptor()); + const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptorAsStringPiece()); mirror::Class* src_class = NULL; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0); @@ -356,7 +356,7 @@ static bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object* StringPrintf("%s has type %s, got %s", UnboxingFailureKind(m, index, f).c_str(), PrettyDescriptor(dst_class).c_str(), - PrettyDescriptor(src_descriptor.c_str()).c_str()).c_str()); + PrettyDescriptor(src_descriptor.data()).c_str()).c_str()); return false; } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 924a1bb..4442ee1 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -80,7 +80,7 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* kla return kNoFailure; } mirror::Class* super = klass->GetSuperClass(); - if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") { + if (super == NULL && ClassHelper(klass).GetDescriptorAsStringPiece() != "Ljava/lang/Object;") { *error = "Verifier rejected class "; *error += PrettyDescriptor(klass); *error += " that has no super class"; @@ -293,6 +293,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca dex_method_idx_(dex_method_idx), mirror_method_(method), method_access_flags_(method_access_flags), + return_type_(nullptr), dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), @@ -300,7 +301,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca code_item_(code_item), declaring_class_(NULL), interesting_dex_pc_(-1), - monitor_enter_dex_pcs_(NULL), + monitor_enter_dex_pcs_(nullptr), have_pending_hard_failure_(false), have_pending_runtime_throw_failure_(false), new_instance_count_(0), @@ -309,7 +310,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca allow_soft_failures_(allow_soft_failures), has_check_casts_(false), has_virtual_or_interface_invokes_(false) { - DCHECK(class_def != NULL); + DCHECK(class_def != nullptr); } void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc, @@ -2131,20 +2132,30 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { inst->Opcode() == Instruction::INVOKE_SUPER_RANGE); mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL, is_range, is_super); - const char* descriptor; - if (called_method == NULL) { + const RegType* return_type = nullptr; + if (called_method != nullptr) { + MethodHelper mh(called_method); + mirror::Class* return_type_class = mh.GetReturnType(); + if (return_type_class != nullptr) { + return_type = ®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, + return_type_class->CannotBeAssignedFromOtherTypes()); + } else { + Thread* self = Thread::Current(); + DCHECK(self->IsExceptionPending()); + self->ClearException(); + } + } + if (return_type == nullptr) { uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; - descriptor = dex_file_->StringByTypeIdx(return_type_idx); - } else { - descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); + const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx); + return_type = ®_types_.FromDescriptor(class_loader_, descriptor, false); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); - if (!return_type.IsLowHalf()) { - work_line_->SetResultRegisterType(return_type); + 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; @@ -2159,7 +2170,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { 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); - is_constructor = StringPiece(dex_file_->GetMethodName(method_id)) == "<init>"; + is_constructor = dex_file_->StringDataAsStringPieceByIdx(method_id.name_idx_) == "<init>"; uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; return_type_descriptor = dex_file_->StringByTypeIdx(return_type_idx); } else { @@ -3497,22 +3508,26 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c()); field = GetInstanceField(object_type, field_idx); } - const char* descriptor; - mirror::ClassLoader* loader; + const RegType* field_type = nullptr; if (field != NULL) { - descriptor = FieldHelper(field).GetTypeDescriptor(); - loader = field->GetDeclaringClass()->GetClassLoader(); - } else { + FieldHelper fh(field); + mirror::Class* field_type_class = fh.GetType(false); + if (field_type_class != nullptr) { + field_type = ®_types_.FromClass(fh.GetTypeDescriptor(), field_type_class, + field_type_class->CannotBeAssignedFromOtherTypes()); + } + } + if (field_type == nullptr) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); - descriptor = dex_file_->GetFieldTypeDescriptor(field_id); - loader = class_loader_; + const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id); + mirror::ClassLoader* loader = class_loader_; + field_type = ®_types_.FromDescriptor(loader, descriptor, false); } - const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false); const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c(); if (is_primitive) { - if (field_type.Equals(insn_type) || - (field_type.IsFloat() && insn_type.IsInteger()) || - (field_type.IsDouble() && insn_type.IsLong())) { + if (field_type->Equals(insn_type) || + (field_type->IsFloat() && insn_type.IsInteger()) || + (field_type->IsDouble() && insn_type.IsLong())) { // expected that read is of the correct primitive type or that int reads are reading // floats or long reads are reading doubles } else { @@ -3525,7 +3540,7 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty return; } } else { - if (!insn_type.IsAssignableFrom(field_type)) { + if (!insn_type.IsAssignableFrom(*field_type)) { Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field) << " to be compatible with type '" << insn_type << "' but found type '" << field_type @@ -3534,10 +3549,10 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty return; } } - if (!field_type.IsLowHalf()) { - work_line_->SetRegisterType(vregA, field_type); + if (!field_type->IsLowHalf()) { + work_line_->SetRegisterType(vregA, *field_type); } else { - work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(®_types_)); + work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(®_types_)); } } @@ -3551,36 +3566,38 @@ void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_ty const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c()); field = GetInstanceField(object_type, field_idx); } - const char* descriptor; - mirror::ClassLoader* loader; - if (field != NULL) { - descriptor = FieldHelper(field).GetTypeDescriptor(); - loader = field->GetDeclaringClass()->GetClassLoader(); - } else { - const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); - descriptor = dex_file_->GetFieldTypeDescriptor(field_id); - loader = class_loader_; - } - const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false); + const RegType* field_type = nullptr; if (field != NULL) { if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) { Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field) << " from other class " << GetDeclaringClass(); return; } + FieldHelper fh(field); + mirror::Class* field_type_class = fh.GetType(false); + if (field_type_class != nullptr) { + field_type = ®_types_.FromClass(fh.GetTypeDescriptor(), field_type_class, + field_type_class->CannotBeAssignedFromOtherTypes()); + } + } + if (field_type == nullptr) { + const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); + const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id); + mirror::ClassLoader* loader = class_loader_; + field_type = ®_types_.FromDescriptor(loader, descriptor, false); } const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c(); if (is_primitive) { - VerifyPrimitivePut(field_type, insn_type, vregA); + VerifyPrimitivePut(*field_type, insn_type, vregA); } else { - if (!insn_type.IsAssignableFrom(field_type)) { + if (!insn_type.IsAssignableFrom(*field_type)) { Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field) << " to be compatible with type '" << insn_type << "' but found type '" << field_type << "' in put-object"; return; } - work_line_->VerifyRegisterType(vregA, field_type); + work_line_->VerifyRegisterType(vregA, *field_type); } } @@ -3648,14 +3665,21 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name(); return; } - const char* descriptor = FieldHelper(field).GetTypeDescriptor(); - mirror::ClassLoader* loader = field->GetDeclaringClass()->GetClassLoader(); - const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false); + FieldHelper fh(field); + mirror::Class* field_type_class = fh.GetType(false); + const RegType* field_type; + if (field_type_class != nullptr) { + field_type = ®_types_.FromClass(fh.GetTypeDescriptor(), field_type_class, + field_type_class->CannotBeAssignedFromOtherTypes()); + } else { + field_type = ®_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(), + fh.GetTypeDescriptor(), false); + } const uint32_t vregA = inst->VRegA_22c(); if (is_primitive) { - if (field_type.Equals(insn_type) || - (field_type.IsFloat() && insn_type.IsIntegralTypes()) || - (field_type.IsDouble() && insn_type.IsLongTypes())) { + if (field_type->Equals(insn_type) || + (field_type->IsFloat() && insn_type.IsIntegralTypes()) || + (field_type->IsDouble() && insn_type.IsLongTypes())) { // expected that read is of the correct primitive type or that int reads are reading // floats or long reads are reading doubles } else { @@ -3668,7 +3692,7 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins return; } } else { - if (!insn_type.IsAssignableFrom(field_type)) { + if (!insn_type.IsAssignableFrom(*field_type)) { Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field) << " to be compatible with type '" << insn_type << "' but found type '" << field_type @@ -3677,10 +3701,10 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins return; } } - if (!field_type.IsLowHalf()) { - work_line_->SetRegisterType(vregA, field_type); + if (!field_type->IsLowHalf()) { + work_line_->SetRegisterType(vregA, *field_type); } else { - work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(®_types_)); + work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(®_types_)); } } @@ -3822,11 +3846,28 @@ InstructionFlags* MethodVerifier::CurrentInsnFlags() { } const RegType& MethodVerifier::GetMethodReturnType() { - const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); - const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id); - uint16_t return_type_idx = proto_id.return_type_idx_; - const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx)); - return reg_types_.FromDescriptor(class_loader_, descriptor, false); + if (return_type_ == nullptr) { + if (mirror_method_ != NULL) { + MethodHelper mh(mirror_method_); + mirror::Class* return_type_class = mh.GetReturnType(); + if (return_type_class != nullptr) { + return_type_ =®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, + return_type_class->CannotBeAssignedFromOtherTypes()); + } else { + Thread* self = Thread::Current(); + DCHECK(self->IsExceptionPending()); + self->ClearException(); + } + } + if (return_type_ == nullptr) { + const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); + const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id); + uint16_t return_type_idx = proto_id.return_type_idx_; + const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx)); + return_type_ = ®_types_.FromDescriptor(class_loader_, descriptor, false); + } + } + return *return_type_; } const RegType& MethodVerifier::GetDeclaringClass() { diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 073a2f7..f143751 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -688,6 +688,7 @@ class MethodVerifier { // Its object representation if known. mirror::ArtMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_); const uint32_t method_access_flags_; // Method's access flags. + const RegType* return_type_; // Lazily computed return type of the method. const DexFile* const dex_file_; // The dex file containing the method. // The dex_cache for the declaring class of the method. mirror::DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_); diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 857acb8..50d1583 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -761,11 +761,6 @@ bool RegType::IsStrictlyAssignableFrom(const RegType& src) const { return AssignableFrom(*this, src, true); } -int32_t ConstantType::ConstantValue() const { - DCHECK(IsConstantTypes()); - return constant_; -} - int32_t ConstantType::ConstantValueLo() const { DCHECK(IsConstantLo()); return constant_; diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h index 865ba20..f371733 100644 --- a/runtime/verifier/reg_type.h +++ b/runtime/verifier/reg_type.h @@ -574,9 +574,12 @@ class ConstantType : public RegType { // If this is a 32-bit constant, what is the value? This value may be imprecise in which case // the value represents part of the integer range of values that may be held in the register. - virtual int32_t ConstantValue() const; - virtual int32_t ConstantValueLo() const; - virtual int32_t ConstantValueHi() const; + int32_t ConstantValue() const { + DCHECK(IsConstantTypes()); + return constant_; + } + int32_t ConstantValueLo() const; + int32_t ConstantValueHi() const; bool IsZero() const { return IsPreciseConstant() && ConstantValue() == 0; diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index ce465a4..fd70300 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -210,6 +210,7 @@ const RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descr } const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) { + DCHECK(klass != nullptr); if (klass->IsPrimitive()) { // Note: precise isn't used for primitive classes. A char is assignable to an int. All // primitive classes are final. |