summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/art_method.h6
-rw-r--r--runtime/mirror/class.cc9
-rw-r--r--runtime/mirror/class.h3
-rw-r--r--runtime/verifier/class_verifier.cc70
-rw-r--r--runtime/verifier/class_verifier.h30
-rw-r--r--runtime/verifier/method_verifier.cc8
-rw-r--r--runtime/verifier/method_verifier.h2
7 files changed, 126 insertions, 2 deletions
diff --git a/runtime/art_method.h b/runtime/art_method.h
index d84ea7c4bc..d4fb5d7b90 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -335,6 +335,11 @@ class ArtMethod final {
DCHECK(!IsNative());
AddAccessFlags(kAccSkipAccessChecks);
}
+ void ClearSkipAccessChecks() {
+ // SkipAccessChecks() is applicable only to non-native methods.
+ DCHECK(!IsNative());
+ ClearAccessFlags(kAccSkipAccessChecks);
+ }
bool PreviouslyWarm() {
if (IsIntrinsic()) {
@@ -363,6 +368,7 @@ class ArtMethod final {
void SetMustCountLocks() {
AddAccessFlags(kAccMustCountLocks);
+ ClearAccessFlags(kAccSkipAccessChecks);
}
// Returns true if this method could be overridden by a default method.
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 455f98d489..a0e8a237c5 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -1031,6 +1031,15 @@ ArtField* Class::FindField(Thread* self,
return nullptr;
}
+void Class::ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) {
+ DCHECK(IsVerified());
+ for (auto& m : GetMethods(pointer_size)) {
+ if (!m.IsNative() && m.IsInvokable()) {
+ m.ClearSkipAccessChecks();
+ }
+ }
+}
+
void Class::SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) {
DCHECK(IsVerified());
for (auto& m : GetMethods(pointer_size)) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6ed20ed02f..d925a96d9c 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1134,6 +1134,9 @@ class MANAGED Class final : public Object {
static ObjPtr<mirror::Class> GetPrimitiveClass(ObjPtr<mirror::String> name)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Clear the kAccSkipAccessChecks flag on each method, for class redefinition.
+ void ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)
+ REQUIRES_SHARED(Locks::mutator_lock_);
// When class is verified, set the kAccSkipAccessChecks flag on each method.
void SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
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) {
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index db5e4f592d..c97ea24799 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -50,6 +50,14 @@ namespace verifier {
// Verifier that ensures the complete class is OK.
class ClassVerifier {
public:
+ // Redo verification on a loaded class. This is for use by class redefinition. Since the class is
+ // already loaded and in use this can only be performed with the mutator lock held.
+ static FailureKind ReverifyClass(Thread* self,
+ ObjPtr<mirror::Class> klass,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error)
+ REQUIRES(Locks::mutator_lock_);
// Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
ObjPtr<mirror::Class> klass,
@@ -70,6 +78,18 @@ class ClassVerifier {
uint32_t api_level,
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
+ static FailureKind 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,
+ bool can_allocate,
+ std::string* error)
+ REQUIRES_SHARED(Locks::mutator_lock_);
static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_);
static void Shutdown();
@@ -78,6 +98,16 @@ class ClassVerifier {
REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ static FailureKind 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)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
DISALLOW_COPY_AND_ASSIGN(ClassVerifier);
};
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 839491ec3e..29bc40c30c 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -5112,6 +5112,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
bool need_precise_constants,
uint32_t api_level,
bool aot_mode,
+ bool allow_suspension,
std::string* hard_failure_msg) {
if (VLOG_IS_ON(verifier_debug)) {
return VerifyMethod<true>(self,
@@ -5131,6 +5132,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
need_precise_constants,
api_level,
aot_mode,
+ allow_suspension,
hard_failure_msg);
} else {
return VerifyMethod<false>(self,
@@ -5150,6 +5152,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
need_precise_constants,
api_level,
aot_mode,
+ allow_suspension,
hard_failure_msg);
}
}
@@ -5172,6 +5175,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
bool need_precise_constants,
uint32_t api_level,
bool aot_mode,
+ bool allow_suspension,
std::string* hard_failure_msg) {
MethodVerifier::FailureData result;
uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0;
@@ -5182,8 +5186,8 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
dex_file,
code_item,
method_idx,
- /* can_load_classes= */ true,
- /* allow_thread_suspension= */ true,
+ /* can_load_classes= */ allow_suspension,
+ /* allow_thread_suspension= */ allow_suspension,
allow_soft_failures,
aot_mode,
dex_cache,
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index aab6ee55c1..09d384a069 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -253,6 +253,7 @@ class MethodVerifier {
bool need_precise_constants,
uint32_t api_level,
bool aot_mode,
+ bool allow_suspension,
std::string* hard_failure_msg)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -274,6 +275,7 @@ class MethodVerifier {
bool need_precise_constants,
uint32_t api_level,
bool aot_mode,
+ bool allow_suspension,
std::string* hard_failure_msg)
REQUIRES_SHARED(Locks::mutator_lock_);