summaryrefslogtreecommitdiff
path: root/runtime/verifier/class_verifier.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2019-10-17 10:32:47 -0700
committer Alex Light <allight@google.com> 2019-10-18 15:51:34 +0000
commitdb55a1121b2437765e732c8bbedf914f8a52f624 (patch)
tree9b1be00c3684703e6a062052a634daa859068333 /runtime/verifier/class_verifier.cc
parent697fe5cc6ce0e9c72c3681152a99a5d5bab4253c (diff)
Class redefinition sometimes needs to update verification
In cases where class redefinition moves a class from having no verification failures to having soft verification failures we need to update the methods with new verification class flags. For example if a method is modified to have unbalanced monitors we need to make sure that future invokes of that method count locks and use the interpreter. Previously we would simply keep the same verification state as the original implementation, causing us to try to compile in situations the compiler cannot handle or leave monitors in inconsistent states. Test: ./test.py --host Bug: 142876078 Change-Id: I8adf59158639bdf237d691b20fad223f0a34db1f
Diffstat (limited to 'runtime/verifier/class_verifier.cc')
-rw-r--r--runtime/verifier/class_verifier.cc70
1 files changed, 70 insertions, 0 deletions
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index 1df11ada50..66f5801634 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -20,6 +20,7 @@
#include <android-base/stringprintf.h>
#include "art_method-inl.h"
+#include "base/enums.h"
#include "base/systrace.h"
#include "base/utils.h"
#include "class_linker.h"
@@ -28,11 +29,13 @@
#include "dex/class_reference.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
+#include "handle.h"
#include "handle_scope-inl.h"
#include "method_verifier-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
#include "runtime.h"
+#include "thread.h"
namespace art {
namespace verifier {
@@ -43,6 +46,30 @@ using android::base::StringPrintf;
// sure we only print this once.
static bool gPrintedDxMonitorText = false;
+FailureKind ClassVerifier::ReverifyClass(Thread* self,
+ ObjPtr<mirror::Class> klass,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error) {
+ DCHECK(!Runtime::Current()->IsAotCompiler());
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> h_klass(hs.NewHandle(klass));
+ ScopedAssertNoThreadSuspension sants(__FUNCTION__);
+ FailureKind res = CommonVerifyClass(self,
+ h_klass.Get(),
+ /*callbacks=*/nullptr,
+ /*allow_soft_failures=*/false,
+ log_level,
+ api_level,
+ /*can_allocate=*/ false,
+ error);
+ if (res == FailureKind::kSoftFailure) {
+ // We cannot skip access checks since there was a soft failure.
+ h_klass->ClearSkipAccessChecksFlagOnAllMethods(kRuntimePointerSize);
+ }
+ return res;
+}
+
FailureKind ClassVerifier::VerifyClass(Thread* self,
ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
@@ -53,6 +80,23 @@ FailureKind ClassVerifier::VerifyClass(Thread* self,
if (klass->IsVerified()) {
return FailureKind::kNoFailure;
}
+ return CommonVerifyClass(self,
+ klass,
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ api_level,
+ /*can_allocate=*/ true,
+ error);
+}
+FailureKind ClassVerifier::CommonVerifyClass(Thread* self,
+ ObjPtr<mirror::Class> klass,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ bool can_allocate,
+ std::string* error) {
bool early_failure = false;
std::string failure_message;
const DexFile& dex_file = klass->GetDexFile();
@@ -89,6 +133,30 @@ FailureKind ClassVerifier::VerifyClass(Thread* self,
allow_soft_failures,
log_level,
api_level,
+ can_allocate,
+ error);
+}
+
+FailureKind ClassVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error) {
+ return VerifyClass(self,
+ dex_file,
+ dex_cache,
+ class_loader,
+ class_def,
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ api_level,
+ /*can_allocate=*/!Runtime::Current()->IsAotCompiler(),
error);
}
@@ -101,6 +169,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self,
bool allow_soft_failures,
HardFailLogMode log_level,
uint32_t api_level,
+ bool can_allocate,
std::string* error) {
// A class must not be abstract and final.
if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
@@ -156,6 +225,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self,
/*need_precise_constants=*/ false,
api_level,
Runtime::Current()->IsAotCompiler(),
+ can_allocate,
&hard_failure_msg);
if (result.kind == FailureKind::kHardFailure) {
if (failure_data.kind == FailureKind::kHardFailure) {