diff options
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 8 | ||||
| -rw-r--r-- | compiler/verifier_deps_test.cc | 38 | ||||
| -rw-r--r-- | runtime/vdex_file.h | 4 | ||||
| -rw-r--r-- | runtime/verifier/verifier_deps.cc | 20 | ||||
| -rw-r--r-- | runtime/verifier/verifier_deps.h | 4 |
5 files changed, 56 insertions, 18 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 0b1bce62c9..bd530ac6a6 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1935,14 +1935,12 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, // time. So instead we assume these classes still need to be verified at // runtime. for (const DexFile* dex_file : dex_files) { - // Fetch the list of unverified classes and turn it into a set for faster - // lookups. - const std::vector<dex::TypeIndex>& unverified_classes = + // Fetch the list of unverified classes. + const std::set<dex::TypeIndex>& unverified_classes = verifier_deps->GetUnverifiedClasses(*dex_file); - std::set<dex::TypeIndex> set(unverified_classes.begin(), unverified_classes.end()); for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); - if (set.find(class_def.class_idx_) == set.end()) { + if (unverified_classes.find(class_def.class_idx_) == unverified_classes.end()) { if (compiler_only_verifies) { // Just update the compiled_classes_ map. The compiler doesn't need to resolve // the type. diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index e9f3f8022d..65389252e2 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -229,8 +229,7 @@ class VerifierDepsTest : public CommonCompilerTest { hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_))); MutableHandle<mirror::Class> cls(hs.NewHandle<mirror::Class>(nullptr)); for (const DexFile* dex_file : dex_files_) { - const std::vector<dex::TypeIndex>& unverified_classes = deps.GetUnverifiedClasses(*dex_file); - std::set<dex::TypeIndex> set(unverified_classes.begin(), unverified_classes.end()); + const std::set<dex::TypeIndex>& unverified_classes = deps.GetUnverifiedClasses(*dex_file); for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); const char* descriptor = dex_file->GetClassDescriptor(class_def); @@ -238,7 +237,7 @@ class VerifierDepsTest : public CommonCompilerTest { if (cls == nullptr) { CHECK(soa.Self()->IsExceptionPending()); soa.Self()->ClearException(); - } else if (set.find(class_def.class_idx_) == set.end()) { + } else if (unverified_classes.find(class_def.class_idx_) == unverified_classes.end()) { ASSERT_EQ(cls->GetStatus(), mirror::Class::kStatusVerified); } else { ASSERT_LT(cls->GetStatus(), mirror::Class::kStatusVerified); @@ -1145,6 +1144,39 @@ TEST_F(VerifierDepsTest, UnverifiedClasses) { ASSERT_TRUE(HasUnverifiedClass("LMyClassWithNoSuperButFailures;")); } +TEST_F(VerifierDepsTest, UnverifiedOrder) { + ScopedObjectAccess soa(Thread::Current()); + jobject loader = LoadDex("VerifierDeps"); + std::vector<const DexFile*> dex_files = GetDexFiles(loader); + ASSERT_GT(dex_files.size(), 0u); + const DexFile* dex_file = dex_files[0]; + VerifierDeps deps1(dex_files); + Thread* const self = Thread::Current(); + ASSERT_TRUE(self->GetVerifierDeps() == nullptr); + self->SetVerifierDeps(&deps1); + deps1.MaybeRecordVerificationStatus(*dex_file, + dex::TypeIndex(0), + verifier::FailureKind::kHardFailure); + deps1.MaybeRecordVerificationStatus(*dex_file, + dex::TypeIndex(1), + verifier::FailureKind::kHardFailure); + VerifierDeps deps2(dex_files); + self->SetVerifierDeps(nullptr); + self->SetVerifierDeps(&deps2); + deps2.MaybeRecordVerificationStatus(*dex_file, + dex::TypeIndex(1), + verifier::FailureKind::kHardFailure); + deps2.MaybeRecordVerificationStatus(*dex_file, + dex::TypeIndex(0), + verifier::FailureKind::kHardFailure); + self->SetVerifierDeps(nullptr); + std::vector<uint8_t> buffer1; + deps1.Encode(dex_files, &buffer1); + std::vector<uint8_t> buffer2; + deps2.Encode(dex_files, &buffer2); + EXPECT_EQ(buffer1, buffer2); +} + TEST_F(VerifierDepsTest, VerifyDeps) { VerifyDexFile(); diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 0351fd3afb..63058cfe6f 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -72,8 +72,8 @@ class VdexFile { private: static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; - // Last update: Change method lookup. - static constexpr uint8_t kVdexVersion[] = { '0', '0', '9', '\0' }; + // Last update: Use set for unverified_classes_. + static constexpr uint8_t kVdexVersion[] = { '0', '1', '0', '\0' }; uint8_t magic_[4]; uint8_t version_[4]; diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 470b0b3d58..0481f24c45 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -59,9 +59,7 @@ void VerifierDeps::MergeWith(const VerifierDeps& other, MergeSets(my_deps->classes_, other_deps.classes_); MergeSets(my_deps->fields_, other_deps.fields_); MergeSets(my_deps->methods_, other_deps.methods_); - for (dex::TypeIndex entry : other_deps.unverified_classes_) { - my_deps->unverified_classes_.push_back(entry); - } + MergeSets(my_deps->unverified_classes_, other_deps.unverified_classes_); } } @@ -507,7 +505,7 @@ void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file, VerifierDeps* thread_deps = GetThreadLocalVerifierDeps(); if (thread_deps != nullptr) { DexFileDeps* dex_deps = thread_deps->GetDexFileDeps(dex_file); - dex_deps->unverified_classes_.push_back(type_idx); + dex_deps->unverified_classes_.insert(type_idx); } } @@ -586,6 +584,16 @@ template<> inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) { return dex::StringIndex(in); } +// TODO: Clean this up, if we use a template arg here it confuses the compiler. +static inline void EncodeTuple(std::vector<uint8_t>* out, const dex::TypeIndex& t) { + EncodeUnsignedLeb128(out, Encode(t)); +} + +// TODO: Clean this up, if we use a template arg here it confuses the compiler. +static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, dex::TypeIndex* t) { + *t = Decode<dex::TypeIndex>(DecodeUint32WithOverflowCheck(in, end)); +} + template<typename T1, typename T2> static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) { EncodeUnsignedLeb128(out, Encode(std::get<0>(t))); @@ -692,7 +700,7 @@ void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files, EncodeSet(buffer, deps.classes_); EncodeSet(buffer, deps.fields_); EncodeSet(buffer, deps.methods_); - EncodeUint16Vector(buffer, deps.unverified_classes_); + EncodeSet(buffer, deps.unverified_classes_); } } @@ -715,7 +723,7 @@ VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, DecodeSet(&data_start, data_end, &deps->classes_); DecodeSet(&data_start, data_end, &deps->fields_); DecodeSet(&data_start, data_end, &deps->methods_); - DecodeUint16Vector(&data_start, data_end, &deps->unverified_classes_); + DecodeSet(&data_start, data_end, &deps->unverified_classes_); } CHECK_LE(data_start, data_end); } diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 2d452f6d6b..4069a1188a 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -117,7 +117,7 @@ class VerifierDeps { bool ValidateDependencies(Handle<mirror::ClassLoader> class_loader, Thread* self) const REQUIRES_SHARED(Locks::mutator_lock_); - const std::vector<dex::TypeIndex>& GetUnverifiedClasses(const DexFile& dex_file) const { + const std::set<dex::TypeIndex>& GetUnverifiedClasses(const DexFile& dex_file) const { return GetDexFileDeps(dex_file)->unverified_classes_; } @@ -197,7 +197,7 @@ class VerifierDeps { std::set<MethodResolution> methods_; // List of classes that were not fully verified in that dex file. - std::vector<dex::TypeIndex> unverified_classes_; + std::set<dex::TypeIndex> unverified_classes_; bool Equals(const DexFileDeps& rhs) const; }; |