From 76c1965179bdf34ed9d0dded046c7ad6f277de3f Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 24 Apr 2017 13:19:09 -0700 Subject: [PATCH] ART: More header cleanup - method_verifier.h Move enumerations to own header. Move the compiler interface (of what the compiler can tolerate) into its own header. Replace or remove method_verifier.h where possible. Test: mmma art Change-Id: I075fcb10b02b6c1c760daad31cb18eaa42067b6d (cherry picked from commit 6d7abbd2324f544c6b6da42bb6b9b531df0ce3cd) --- compiler/driver/compiler_driver.cc | 20 +++--- compiler/oat_writer.cc | 1 - compiler/optimizing/optimizing_compiler.cc | 4 +- compiler/verifier_deps_test.cc | 5 +- runtime/Android.bp | 2 +- runtime/class_linker.cc | 28 ++++---- runtime/class_linker.h | 7 +- runtime/interpreter/interpreter_common.cc | 1 - runtime/openjdkjvmti/ti_redefine.cc | 6 +- runtime/quick_exception_handler.cc | 1 - runtime/runtime_options.h | 14 ++-- runtime/verifier/method_verifier.cc | 66 +++++++++-------- runtime/verifier/method_verifier.h | 70 +----------------- runtime/verifier/method_verifier_test.cc | 10 +-- runtime/verifier/verifier_compiler_binding.h | 40 +++++++++++ runtime/verifier/verifier_deps.cc | 6 +- runtime/verifier/verifier_deps.h | 21 ++++-- runtime/verifier/verifier_enums.h | 102 +++++++++++++++++++++++++++ runtime/verifier/verifier_log_mode.h | 33 --------- runtime/verifier/verify_mode.h | 35 --------- 20 files changed, 242 insertions(+), 230 deletions(-) create mode 100644 runtime/verifier/verifier_compiler_binding.h create mode 100644 runtime/verifier/verifier_enums.h delete mode 100644 runtime/verifier/verifier_log_mode.h delete mode 100644 runtime/verifier/verify_mode.h diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 805c5dadc..f77b3ddfe 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -78,8 +78,8 @@ #include "vdex_file.h" #include "verifier/method_verifier.h" #include "verifier/method_verifier-inl.h" -#include "verifier/verifier_log_mode.h" #include "verifier/verifier_deps.h" +#include "verifier/verifier_enums.h" namespace art { @@ -2132,7 +2132,7 @@ class VerifyClassVisitor : public CompilationVisitor { hs.NewHandle(soa.Decode(jclass_loader))); Handle klass( hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); - verifier::MethodVerifier::FailureKind failure_kind; + verifier::FailureKind failure_kind; if (klass == nullptr) { CHECK(soa.Self()->IsExceptionPending()); soa.Self()->ClearException(); @@ -2155,7 +2155,7 @@ class VerifyClassVisitor : public CompilationVisitor { true /* allow soft failures */, log_level_, &error_msg); - if (failure_kind == verifier::MethodVerifier::kHardFailure) { + if (failure_kind == verifier::FailureKind::kHardFailure) { LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor) << " because: " << error_msg; manager_->GetCompiler()->SetHadHardVerifierFailure(); @@ -2163,10 +2163,10 @@ class VerifyClassVisitor : public CompilationVisitor { // Force a soft failure for the VerifierDeps. This is a sanity measure, as // the vdex file already records that the class hasn't been resolved. It avoids // trying to do future verification optimizations when processing the vdex file. - DCHECK(failure_kind == verifier::MethodVerifier::kSoftFailure || - failure_kind == verifier::MethodVerifier::kNoFailure) + DCHECK(failure_kind == verifier::FailureKind::kSoftFailure || + failure_kind == verifier::FailureKind::kNoFailure) << failure_kind; - failure_kind = verifier::MethodVerifier::kSoftFailure; + failure_kind = verifier::FailureKind::kSoftFailure; } } else if (!SkipClass(jclass_loader, dex_file, klass.Get())) { CHECK(klass->IsResolved()) << klass->PrettyClass(); @@ -2198,16 +2198,16 @@ class VerifyClassVisitor : public CompilationVisitor { << " failed to fully verify: state= " << klass->GetStatus(); } if (klass->IsVerified()) { - DCHECK_EQ(failure_kind, verifier::MethodVerifier::kNoFailure); + DCHECK_EQ(failure_kind, verifier::FailureKind::kNoFailure); } else if (klass->ShouldVerifyAtRuntime()) { - DCHECK_EQ(failure_kind, verifier::MethodVerifier::kSoftFailure); + DCHECK_EQ(failure_kind, verifier::FailureKind::kSoftFailure); } else { - DCHECK_EQ(failure_kind, verifier::MethodVerifier::kHardFailure); + DCHECK_EQ(failure_kind, verifier::FailureKind::kHardFailure); } } } else { // Make the skip a soft failure, essentially being considered as verify at runtime. - failure_kind = verifier::MethodVerifier::kSoftFailure; + failure_kind = verifier::FailureKind::kSoftFailure; } verifier::VerifierDeps::MaybeRecordVerificationStatus( dex_file, class_def.class_idx_, failure_kind); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 1781643af..af60def11 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -55,7 +55,6 @@ #include "type_lookup_table.h" #include "utils/dex_cache_arrays_layout-inl.h" #include "vdex_file.h" -#include "verifier/method_verifier.h" #include "verifier/verifier_deps.h" #include "zip_archive.h" diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 8aad53985..065c11edd 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -98,7 +98,7 @@ #include "ssa_liveness_analysis.h" #include "ssa_phi_elimination.h" #include "utils/assembler.h" -#include "verifier/method_verifier.h" +#include "verifier/verifier_compiler_binding.h" namespace art { @@ -1041,7 +1041,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx); DCHECK(!verified_method->HasRuntimeThrow()); if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) - || verifier::MethodVerifier::CanCompilerHandleVerificationFailure( + || verifier::CanCompilerHandleVerificationFailure( verified_method->GetEncounteredVerificationFailures())) { ArenaAllocator arena(Runtime::Current()->GetArenaPool()); CodeVectorAllocator code_allocator(&arena); diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index 0b1ab758b..4d55eb08b 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -28,12 +28,13 @@ #include "driver/compiler_options.h" #include "driver/compiler_driver.h" #include "handle_scope-inl.h" -#include "verifier/method_verifier-inl.h" +#include "indenter.h" #include "mirror/class_loader.h" #include "runtime.h" -#include "thread.h" #include "scoped_thread_state_change-inl.h" +#include "thread.h" #include "utils/atomic_method_ref_map-inl.h" +#include "verifier/method_verifier-inl.h" namespace art { namespace verifier { diff --git a/runtime/Android.bp b/runtime/Android.bp index 0860b2e89..cff2cbccd 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -457,7 +457,7 @@ gensrcs { "thread.h", "thread_state.h", "ti/agent.h", - "verifier/method_verifier.h", + "verifier/verifier_enums.h", ], output_extension: "operator_out.cc", } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index ee33fc4c9..3ecf59520 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3981,7 +3981,7 @@ static void EnsureSkipAccessChecksMethods(Handle klass, PointerSi } } -verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( +verifier::FailureKind ClassLinker::VerifyClass( Thread* self, Handle klass, verifier::HardFailLogMode log_level) { { // TODO: assert that the monitor on the Class is held @@ -4003,19 +4003,19 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( // this class as a parent to another. if (klass->IsErroneous()) { ThrowEarlierClassFailure(klass.Get()); - return verifier::MethodVerifier::kHardFailure; + return verifier::FailureKind::kHardFailure; } // Don't attempt to re-verify if already verified. if (klass->IsVerified()) { EnsureSkipAccessChecksMethods(klass, image_pointer_size_); - return verifier::MethodVerifier::kNoFailure; + return verifier::FailureKind::kNoFailure; } // For AOT, don't attempt to re-verify if we have already found we should // verify at runtime. if (Runtime::Current()->IsAotCompiler() && klass->ShouldVerifyAtRuntime()) { - return verifier::MethodVerifier::kSoftFailure; + return verifier::FailureKind::kSoftFailure; } if (klass->GetStatus() == mirror::Class::kStatusResolved) { @@ -4031,7 +4031,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( if (!Runtime::Current()->IsVerificationEnabled()) { mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); EnsureSkipAccessChecksMethods(klass, image_pointer_size_); - return verifier::MethodVerifier::kNoFailure; + return verifier::FailureKind::kNoFailure; } } @@ -4041,7 +4041,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( // If we have a superclass and we get a hard verification failure we can return immediately. if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) { CHECK(self->IsExceptionPending()) << "Verification error should be pending."; - return verifier::MethodVerifier::kHardFailure; + return verifier::FailureKind::kHardFailure; } // Verify all default super-interfaces. @@ -4068,7 +4068,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( } else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) { // We had a hard failure while verifying this interface. Just return immediately. CHECK(self->IsExceptionPending()) << "Verification error should be pending."; - return verifier::MethodVerifier::kHardFailure; + return verifier::FailureKind::kHardFailure; } else if (UNLIKELY(!iface->IsVerified())) { // We softly failed to verify the iface. Stop checking and clean up. // Put the iface into the supertype handle so we know what caused us to fail. @@ -4095,7 +4095,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( DCHECK(!mirror::Class::IsErroneous(oat_file_class_status) || !preverified); std::string error_msg; - verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure; + verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure; if (!preverified) { Runtime* runtime = Runtime::Current(); verifier_failure = verifier::MethodVerifier::VerifyClass(self, @@ -4109,8 +4109,8 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( // Verification is done, grab the lock again. ObjectLock lock(self, klass); - if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) { - if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) { + if (preverified || verifier_failure != verifier::FailureKind::kHardFailure) { + if (!preverified && verifier_failure != verifier::FailureKind::kNoFailure) { VLOG(class_linker) << "Soft verification failure in class " << klass->PrettyDescriptor() << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8() @@ -4119,7 +4119,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( self->AssertNoPendingException(); // Make sure all classes referenced by catch blocks are resolved. ResolveClassExceptionHandlerTypes(klass); - if (verifier_failure == verifier::MethodVerifier::kNoFailure) { + if (verifier_failure == verifier::FailureKind::kNoFailure) { // Even though there were no verifier failures we need to respect whether the super-class and // super-default-interfaces were verified or requiring runtime reverification. if (supertype == nullptr || supertype->IsVerified()) { @@ -4128,10 +4128,10 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( CHECK_EQ(supertype->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime); mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self); // Pretend a soft failure occurred so that we don't consider the class verified below. - verifier_failure = verifier::MethodVerifier::kSoftFailure; + verifier_failure = verifier::FailureKind::kSoftFailure; } } else { - CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure); + CHECK_EQ(verifier_failure, verifier::FailureKind::kSoftFailure); // Soft failures at compile time should be retried at runtime. Soft // failures at runtime will be handled by slow paths in the generated // code. Set status accordingly. @@ -4152,7 +4152,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass( ThrowVerifyError(klass.Get(), "%s", error_msg.c_str()); mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self); } - if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) { + if (preverified || verifier_failure == verifier::FailureKind::kNoFailure) { // Class is verified so we don't need to do any access check on its methods. // Let the interpreter know it by setting the kAccSkipAccessChecks flag onto each // method. diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 1c280a466..7f652ecc9 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -24,9 +24,7 @@ #include #include -#include "base/allocator.h" #include "base/enums.h" -#include "base/hash_set.h" #include "base/macros.h" #include "base/mutex.h" #include "class_table.h" @@ -38,8 +36,7 @@ #include "jni.h" #include "mirror/class.h" #include "object_callbacks.h" -#include "verifier/method_verifier.h" -#include "verifier/verifier_log_mode.h" +#include "verifier/verifier_enums.h" namespace art { @@ -453,7 +450,7 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); - verifier::MethodVerifier::FailureKind VerifyClass( + verifier::FailureKind VerifyClass( Thread* self, Handle klass, verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone) diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 326f5c96c..ef0ddb30d 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -32,7 +32,6 @@ #include "reflection.h" #include "reflection-inl.h" #include "stack.h" -#include "verifier/method_verifier.h" #include "well_known_classes.h" namespace art { diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc index 41ed86237..cca148697 100644 --- a/runtime/openjdkjvmti/ti_redefine.cc +++ b/runtime/openjdkjvmti/ti_redefine.cc @@ -66,7 +66,7 @@ #include "ti_class_loader.h" #include "transform.h" #include "verifier/method_verifier.h" -#include "verifier/verifier_log_mode.h" +#include "verifier/verifier_enums.h" namespace openjdkjvmti { @@ -1063,7 +1063,7 @@ bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& art::StackHandleScope<2> hs(driver_->self_); std::string error; // TODO Make verification log level lower - art::verifier::MethodVerifier::FailureKind failure = + art::verifier::FailureKind failure = art::verifier::MethodVerifier::VerifyClass(driver_->self_, dex_file_.get(), hs.NewHandle(iter.GetNewDexCache()), @@ -1074,7 +1074,7 @@ bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& /*log_level*/ art::verifier::HardFailLogMode::kLogWarning, &error); - bool passes = failure == art::verifier::MethodVerifier::kNoFailure; + bool passes = failure == art::verifier::FailureKind::kNoFailure; if (!passes) { RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error); } diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 72e050045..b8669412f 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -32,7 +32,6 @@ #include "oat_quick_method_header.h" #include "stack.h" #include "stack_map.h" -#include "verifier/method_verifier.h" namespace art { diff --git a/runtime/runtime_options.h b/runtime/runtime_options.h index 5fcb86e3f..c50999253 100644 --- a/runtime/runtime_options.h +++ b/runtime/runtime_options.h @@ -17,13 +17,15 @@ #ifndef ART_RUNTIME_RUNTIME_OPTIONS_H_ #define ART_RUNTIME_RUNTIME_OPTIONS_H_ -#include "base/variant_map.h" -#include "cmdline_types.h" // TODO: don't need to include this file here - -// Map keys #include #include + +#include +#include + #include "base/logging.h" +#include "base/variant_map.h" +#include "cmdline_types.h" // TODO: don't need to include this file here #include "jdwp/jdwp.h" #include "jit/jit.h" #include "jit/jit_code_cache.h" @@ -31,9 +33,7 @@ #include "gc/space/large_object_space.h" #include "arch/instruction_set.h" #include "jit/profile_saver_options.h" -#include "verifier/verify_mode.h" -#include -#include +#include "verifier/verifier_enums.h" namespace art { diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index e09f95ce4..c89352e8b 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -36,6 +36,7 @@ #include "dex_instruction_visitor.h" #include "experimental_flags.h" #include "gc/accounting/card_table-inl.h" +#include "handle_scope-inl.h" #include "indenter.h" #include "intern_table.h" #include "leb128.h" @@ -52,7 +53,7 @@ #include "scoped_thread_state_change-inl.h" #include "utils.h" #include "verifier_deps.h" -#include "handle_scope-inl.h" +#include "verifier_compiler_binding.h" namespace art { namespace verifier { @@ -136,14 +137,14 @@ static void SafelyMarkAllRegistersAsConflicts(MethodVerifier* verifier, Register reg_line->MarkAllRegistersAsConflicts(verifier); } -MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self, - mirror::Class* klass, - CompilerCallbacks* callbacks, - bool allow_soft_failures, - HardFailLogMode log_level, - std::string* error) { +FailureKind MethodVerifier::VerifyClass(Thread* self, + mirror::Class* klass, + CompilerCallbacks* callbacks, + bool allow_soft_failures, + HardFailLogMode log_level, + std::string* error) { if (klass->IsVerified()) { - return kNoFailure; + return FailureKind::kNoFailure; } bool early_failure = false; std::string failure_message; @@ -167,7 +168,7 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self, ClassReference ref(&dex_file, klass->GetDexClassDefIndex()); callbacks->ClassRejected(ref); } - return kHardFailure; + return FailureKind::kHardFailure; } StackHandleScope<2> hs(self); Handle dex_cache(hs.NewHandle(klass->GetDexCache())); @@ -188,12 +189,9 @@ static bool HasNextMethod(ClassDataItemIterator* it) { return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod(); } -static MethodVerifier::FailureKind FailureKindMax(MethodVerifier::FailureKind fk1, - MethodVerifier::FailureKind fk2) { - static_assert(MethodVerifier::FailureKind::kNoFailure < - MethodVerifier::FailureKind::kSoftFailure - && MethodVerifier::FailureKind::kSoftFailure < - MethodVerifier::FailureKind::kHardFailure, +static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) { + static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure + && FailureKind::kSoftFailure < FailureKind::kHardFailure, "Unexpected FailureKind order"); return std::max(fk1, fk2); } @@ -257,8 +255,8 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self, log_level, need_precise_constants, &hard_failure_msg); - if (result.kind == kHardFailure) { - if (failure_data.kind == kHardFailure) { + if (result.kind == FailureKind::kHardFailure) { + if (failure_data.kind == FailureKind::kHardFailure) { // If we logged an error before, we need a newline. *error_string += "\n"; } else { @@ -277,15 +275,15 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self, return failure_data; } -MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self, - const DexFile* dex_file, - Handle dex_cache, - Handle class_loader, - const DexFile::ClassDef& class_def, - CompilerCallbacks* callbacks, - bool allow_soft_failures, - HardFailLogMode log_level, - std::string* error) { +FailureKind MethodVerifier::VerifyClass(Thread* self, + const DexFile* dex_file, + Handle dex_cache, + Handle class_loader, + const DexFile::ClassDef& class_def, + CompilerCallbacks* callbacks, + bool allow_soft_failures, + HardFailLogMode log_level, + std::string* error) { ScopedTrace trace(__FUNCTION__); // A class must not be abstract and final. @@ -293,13 +291,13 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self, *error = "Verifier rejected class "; *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); *error += ": class is abstract and final."; - return kHardFailure; + return FailureKind::kHardFailure; } const uint8_t* class_data = dex_file->GetClassData(class_def); if (class_data == nullptr) { // empty class, probably a marker interface - return kNoFailure; + return FailureKind::kNoFailure; } ClassDataItemIterator it(*dex_file, class_data); while (it.HasNextStaticField() || it.HasNextInstanceField()) { @@ -335,8 +333,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self, data1.Merge(data2); - if (data1.kind == kNoFailure) { - return kNoFailure; + if (data1.kind == FailureKind::kNoFailure) { + return FailureKind::kNoFailure; } else { if ((data1.types & VERIFY_ERROR_LOCKING) != 0) { // Print a warning about expected slow-down. Use a string temporary to print one contiguous @@ -412,7 +410,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, verifier.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in " << dex_file->PrettyMethod(method_idx) << "\n"); } - result.kind = kSoftFailure; + result.kind = FailureKind::kSoftFailure; if (method != nullptr && !CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) { method->SetDontCompile(); @@ -432,7 +430,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, // code is valid (even the dead and unverified one). As such this is done only for apps. // (CompilerDriver DCHECKs in VerifyClassVisitor that methods from boot image are // fully verified). - result.kind = kSoftFailure; + result.kind = FailureKind::kSoftFailure; } } if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) { @@ -446,7 +444,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, if (UNLIKELY(verifier.have_pending_experimental_failure_)) { // Failed due to being forced into interpreter. This is ok because // we just want to skip verification. - result.kind = kSoftFailure; + result.kind = FailureKind::kSoftFailure; } else { CHECK(verifier.have_pending_hard_failure_); if (VLOG_IS_ON(verifier)) { @@ -477,7 +475,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, *hard_failure_msg = verifier.failure_messages_[verifier.failure_messages_.size() - 1]->str(); } - result.kind = kHardFailure; + result.kind = FailureKind::kHardFailure; if (callbacks != nullptr) { // Let the interested party know that we failed the class. diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 7b67967c2..26dc15e24 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -33,7 +33,7 @@ #include "method_reference.h" #include "register_line.h" #include "reg_type_cache.h" -#include "verifier_log_mode.h" +#include "verifier_enums.h" namespace art { @@ -50,57 +50,6 @@ class RegisterLine; using RegisterLineArenaUniquePtr = std::unique_ptr; class RegType; -/* - * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the - * method determines which list we search, and whether we travel up into superclasses. - * - * (, , and methods declared "private" or "static" are stored in the "direct" list. - * All others are stored in the "virtual" list.) - */ -enum MethodType { - METHOD_UNKNOWN = 0, - METHOD_DIRECT, // , private - METHOD_STATIC, // static - METHOD_VIRTUAL, // virtual - METHOD_SUPER, // super - METHOD_INTERFACE, // interface - METHOD_POLYMORPHIC // polymorphic -}; -std::ostream& operator<<(std::ostream& os, const MethodType& rhs); - -/* - * An enumeration of problems that can turn up during verification. - * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause - * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure - * that can potentially be corrected, and the verifier will try again at runtime. - * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause - * the class to remain uncompiled. Other errors denote verification errors that cause bytecode - * to be rewritten to fail at runtime. - */ -enum VerifyError { - VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation. - VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime. - - VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError. - VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError. - VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError. - VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError. - VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError. - VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError. - VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError. - VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError. - // For opcodes that don't have complete verifier support, we need a way to continue - // execution at runtime without attempting to re-verify (since we know it will fail no - // matter what). Instead, run as the interpreter in a special "do access checks" mode - // which will perform verifier-like checking on the fly. - VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime; - // force the interpreter to do access checks. - // (sets a soft fail at compile time). - VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be - // punted to the interpreter with access checks. -}; -std::ostream& operator<<(std::ostream& os, const VerifyError& rhs); - // We don't need to store the register data for many instructions, because we either only need // it at branch points (for verification) or GC points and branches (for verification + // type-precise register analysis). @@ -136,20 +85,6 @@ class PcToRegisterLineTable { // The verifier class MethodVerifier { public: - enum FailureKind { - kNoFailure, - kSoftFailure, - kHardFailure, - }; - - static bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) { - constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS - | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS - | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD - | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD; - return (encountered_failure_types & (~unresolved_mask)) == 0; - } - // Verify a class. Returns "kNoFailure" on success. static FailureKind VerifyClass(Thread* self, mirror::Class* klass, @@ -325,7 +260,7 @@ class MethodVerifier { // Verification result for method(s). Includes a (maximum) failure kind, and (the union of) // all failure types. struct FailureData : ValueObject { - FailureKind kind = kNoFailure; + FailureKind kind = FailureKind::kNoFailure; uint32_t types = 0U; // Merge src into this. Uses the most severe failure kind, and the union of types. @@ -869,7 +804,6 @@ class MethodVerifier { DISALLOW_COPY_AND_ASSIGN(MethodVerifier); }; -std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs); } // namespace verifier } // namespace art diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc index bdb6b6879..d9874677e 100644 --- a/runtime/verifier/method_verifier_test.cc +++ b/runtime/verifier/method_verifier_test.cc @@ -26,7 +26,7 @@ #include "dex_file-inl.h" #include "scoped_thread_state_change-inl.h" #include "utils.h" -#include "verifier_log_mode.h" +#include "verifier_enums.h" namespace art { namespace verifier { @@ -41,15 +41,15 @@ class MethodVerifierTest : public CommonRuntimeTest { // Verify the class std::string error_msg; - MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass( + FailureKind failure = MethodVerifier::VerifyClass( self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg); if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) { - ASSERT_TRUE(failure == MethodVerifier::kSoftFailure || - failure == MethodVerifier::kNoFailure) << error_msg; + ASSERT_TRUE(failure == FailureKind::kSoftFailure || + failure == FailureKind::kNoFailure) << error_msg; } else { - ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg; + ASSERT_TRUE(failure == FailureKind::kNoFailure) << error_msg; } } diff --git a/runtime/verifier/verifier_compiler_binding.h b/runtime/verifier/verifier_compiler_binding.h new file mode 100644 index 000000000..4f9a13f77 --- /dev/null +++ b/runtime/verifier/verifier_compiler_binding.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_ +#define ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_ + +#include + +#include "base/macros.h" +#include "verifier_enums.h" + +namespace art { +namespace verifier { + +ALWAYS_INLINE +static inline bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) { + constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS + | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS + | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD + | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD; + return (encountered_failure_types & (~unresolved_mask)) == 0; +} + +} // namespace verifier +} // namespace art + +#endif // ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_ diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 0497a6d6d..122e05f07 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -23,8 +23,10 @@ #include "base/stl_util.h" #include "compiler_callbacks.h" #include "dex_file-inl.h" +#include "indenter.h" #include "leb128.h" #include "mirror/class-inl.h" +#include "mirror/class_loader.h" #include "obj_ptr-inl.h" #include "runtime.h" @@ -502,8 +504,8 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file, dex::TypeIndex type_idx, - MethodVerifier::FailureKind failure_kind) { - if (failure_kind == MethodVerifier::kNoFailure) { + FailureKind failure_kind) { + if (failure_kind == FailureKind::kNoFailure) { // We only record classes that did not fully verify at compile time. return; } diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 11750fd96..d69e4dcff 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -21,17 +21,26 @@ #include #include -#include "art_field.h" -#include "art_method.h" #include "base/array_ref.h" #include "base/mutex.h" -#include "indenter.h" +#include "handle.h" #include "method_resolution_kind.h" -#include "method_verifier.h" // For MethodVerifier::FailureKind. #include "obj_ptr.h" -#include "os.h" +#include "thread.h" +#include "verifier_enums.h" // For MethodVerifier::FailureKind. namespace art { + +class ArtField; +class ArtMethod; +class DexFile; +class VariableIndentationOutputStream; + +namespace mirror { +class Class; +class ClassLoader; +} + namespace verifier { // Verification dependencies collector class used by the MethodVerifier to record @@ -59,7 +68,7 @@ class VerifierDeps { // Record the verification status of the class at `type_idx`. static void MaybeRecordVerificationStatus(const DexFile& dex_file, dex::TypeIndex type_idx, - MethodVerifier::FailureKind failure_kind) + FailureKind failure_kind) REQUIRES(!Locks::verifier_deps_lock_); // Record the outcome `klass` of resolving type `type_idx` from `dex_file`. diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h new file mode 100644 index 000000000..bbdd45dd5 --- /dev/null +++ b/runtime/verifier/verifier_enums.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_ +#define ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_ + +#include + +namespace art { +namespace verifier { + +// The mode that the verifier should run as. +enum class VerifyMode : int8_t { + kNone, // Everything is assumed verified. + kEnable, // Standard verification, try pre-verifying at compile-time. + kSoftFail, // Force a soft fail, punting to the interpreter with access checks. +}; + +// The outcome of verification. +enum class FailureKind { + kNoFailure, + kSoftFailure, + kHardFailure, +}; +std::ostream& operator<<(std::ostream& os, const FailureKind& rhs); + +// How to log hard failures during verification. +enum class HardFailLogMode { + kLogNone, // Don't log hard failures at all. + kLogVerbose, // Log with severity VERBOSE. + kLogWarning, // Log with severity WARNING. + kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT +}; + +/* + * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the + * method determines which list we search, and whether we travel up into superclasses. + * + * (, , and methods declared "private" or "static" are stored in the "direct" list. + * All others are stored in the "virtual" list.) + */ +enum MethodType { + METHOD_UNKNOWN = 0, + METHOD_DIRECT, // , private + METHOD_STATIC, // static + METHOD_VIRTUAL, // virtual + METHOD_SUPER, // super + METHOD_INTERFACE, // interface + METHOD_POLYMORPHIC // polymorphic +}; +std::ostream& operator<<(std::ostream& os, const MethodType& rhs); + +/* + * An enumeration of problems that can turn up during verification. + * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause + * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure + * that can potentially be corrected, and the verifier will try again at runtime. + * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause + * the class to remain uncompiled. Other errors denote verification errors that cause bytecode + * to be rewritten to fail at runtime. + */ +enum VerifyError { + VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation. + VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime. + + VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError. + VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError. + VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError. + VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError. + VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError. + VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError. + VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError. + VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError. + // For opcodes that don't have complete verifier support, we need a way to continue + // execution at runtime without attempting to re-verify (since we know it will fail no + // matter what). Instead, run as the interpreter in a special "do access checks" mode + // which will perform verifier-like checking on the fly. + VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime; + // force the interpreter to do access checks. + // (sets a soft fail at compile time). + VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be + // punted to the interpreter with access checks. +}; +std::ostream& operator<<(std::ostream& os, const VerifyError& rhs); + +} // namespace verifier +} // namespace art + +#endif // ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_ diff --git a/runtime/verifier/verifier_log_mode.h b/runtime/verifier/verifier_log_mode.h deleted file mode 100644 index e83d1749c..000000000 --- a/runtime/verifier/verifier_log_mode.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_ -#define ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_ - -namespace art { -namespace verifier { - -enum class HardFailLogMode { - kLogNone, // Don't log hard failures at all. - kLogVerbose, // Log with severity VERBOSE. - kLogWarning, // Log with severity WARNING. - kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT -}; - -} // namespace verifier -} // namespace art - -#endif // ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_ diff --git a/runtime/verifier/verify_mode.h b/runtime/verifier/verify_mode.h deleted file mode 100644 index bea43787c..000000000 --- a/runtime/verifier/verify_mode.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_VERIFIER_VERIFY_MODE_H_ -#define ART_RUNTIME_VERIFIER_VERIFY_MODE_H_ - -#include - -namespace art { -namespace verifier { - -// The mode that the verifier should run as. -enum class VerifyMode : int8_t { - kNone, // Everything is assumed verified. - kEnable, // Standard verification, try pre-verifying at compile-time. - kSoftFail, // Force a soft fail, punting to the interpreter with access checks. -}; - -} // namespace verifier -} // namespace art - -#endif // ART_RUNTIME_VERIFIER_VERIFY_MODE_H_ -- 2.11.0