summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-05-26 21:34:09 -0700
committerAndreas Gampe <agampe@google.com>2015-05-27 08:24:03 -0700
commit3b45ef277e4a5f7e0314d5df7ef82e480156ba75 (patch)
tree1df28568b9e7e4e50102b7f834fab6e943c444a5 /runtime
parentc06841dac1443e99e92596f15caa82c99bfee010 (diff)
downloadart-3b45ef277e4a5f7e0314d5df7ef82e480156ba75.tar.gz
art-3b45ef277e4a5f7e0314d5df7ef82e480156ba75.tar.bz2
art-3b45ef277e4a5f7e0314d5df7ef82e480156ba75.zip
ART: Fix VerifyObject runtime verification
Update some bit-rotted code to work again. Most tests now work, for some the verification overhead results in a timeout. Change-Id: Ieab4f2de474a05e915e24abc93da3c2eeed996eb
Diffstat (limited to 'runtime')
-rw-r--r--runtime/entrypoints/quick/callee_save_frame.h15
-rw-r--r--runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc4
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc5
-rw-r--r--runtime/mirror/array-inl.h4
-rw-r--r--runtime/mirror/array.h4
-rw-r--r--runtime/mirror/object-inl.h12
-rw-r--r--runtime/mirror/object.h2
7 files changed, 31 insertions, 15 deletions
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 8cd6ca6777..3bcaf93e6d 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -38,22 +38,24 @@ class ArtMethod;
class ScopedQuickEntrypointChecks {
public:
- explicit ScopedQuickEntrypointChecks(Thread *self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(self) {
- if (kIsDebugBuild) {
+ explicit ScopedQuickEntrypointChecks(Thread *self,
+ bool entry_check = kIsDebugBuild,
+ bool exit_check = kIsDebugBuild)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : self_(self), exit_check_(exit_check) {
+ if (entry_check) {
TestsOnEntry();
}
}
- explicit ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(kIsDebugBuild ? Thread::Current() : nullptr) {
+ ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : self_(kIsDebugBuild ? Thread::Current() : nullptr), exit_check_(kIsDebugBuild) {
if (kIsDebugBuild) {
TestsOnEntry();
}
}
~ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (kIsDebugBuild) {
+ if (exit_check_) {
TestsOnExit();
}
}
@@ -70,6 +72,7 @@ class ScopedQuickEntrypointChecks {
}
Thread* const self_;
+ bool exit_check_;
};
static constexpr size_t GetCalleeSaveFrameSize(InstructionSet isa, Runtime::CalleeSaveType type) {
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index eb1b1056a4..2bb73efa2f 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -29,7 +29,9 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(mirror::ArtMethod*
Thread* self,
uintptr_t lr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // Instrumentation changes the stack. Thus, when exiting, the stack cannot be verified, so skip
+ // that part.
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
const void* result;
if (instrumentation->IsDeoptimized(method)) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 838427fcb6..227c5b0417 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -823,7 +823,10 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // The resolution trampoline stashes the resolved method into the callee-save frame to transport
+ // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely
+ // does not have the same stack layout as the callee-save method).
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
// Start new JNI local reference state
JNIEnvExt* env = self->GetJniEnv();
ScopedObjectAccessUnchecked soa(env);
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 8b3418d6be..9696dcd754 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -237,7 +237,7 @@ inline void PrimitiveArray<T>::Set(int32_t i, T value) {
}
template<typename T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -245,7 +245,7 @@ inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
if (kTransactionActive) {
Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
}
- DCHECK(CheckIsValidIndex(i));
+ DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
GetData()[i] = value;
}
// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 832ad68dcd..167f824d14 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -131,7 +131,9 @@ class MANAGED PrimitiveArray : public Array {
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
/*
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 39d0f5664f..7760ea2cfd 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -59,19 +59,23 @@ inline void Object::SetClass(Class* new_klass) {
OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
}
+template<VerifyObjectFlags kVerifyFlags>
inline LockWord Object::GetLockWord(bool as_volatile) {
if (as_volatile) {
- return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
- return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
+template<VerifyObjectFlags kVerifyFlags>
inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
// Force use of non-transactional mode and do not check.
if (as_volatile) {
- SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32Volatile<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
} else {
- SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
}
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 5afe99f3f8..2c0e626771 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -125,7 +125,9 @@ class MANAGED LOCKABLE Object {
// As_volatile can be false if the mutators are suspended. This is an optimization since it
// avoids the barriers.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
LockWord GetLockWord(bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetLockWord(LockWord new_val, bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);