Fix stale root error in verifier
There was a stale root error caused by the static roots from
the reg types. These were visitied if there was an active verifier
in the method_verifiers_ but this is not always the case when a GC
is run. The fix is to always visit the static method verifier roots.
This only showed up as a bug without an image since these roots
were primitive classes and always in the image, and therefore
didn't ever need to be updated due to moving GC.
(cherry picked from commit 6167864e28e4e12658ebdbaf1d5239acdaf4aaa4)
Change-Id: I592f2770570de97b431671cfbd409f63697892f1
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index bf1e016..b4a09e5 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1147,6 +1147,7 @@
callee_save_methods_[i].VisitRoot(callback, arg, 0, kRootVMInternal);
}
}
+ verifier::MethodVerifier::VisitStaticRoots(callback, arg);
{
MutexLock mu(Thread::Current(), method_verifier_lock_);
for (verifier::MethodVerifier* verifier : method_verifiers_) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f90da15..b799588 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4181,6 +4181,10 @@
verifier::RegTypeCache::ShutDown();
}
+void MethodVerifier::VisitStaticRoots(RootCallback* callback, void* arg) {
+ RegTypeCache::VisitStaticRoots(callback, arg);
+}
+
void MethodVerifier::VisitRoots(RootCallback* callback, void* arg) {
reg_types_.VisitRoots(callback, arg);
}
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 81ab960..eef2b9e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -221,6 +221,8 @@
// Describe VRegs at the given dex pc.
std::vector<int32_t> DescribeVRegs(uint32_t dex_pc);
+ static void VisitStaticRoots(RootCallback* callback, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Accessors used by the compiler via CompilerCallback
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 121fccb..bffec4b 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -555,6 +555,28 @@
}
}
+void RegTypeCache::VisitStaticRoots(RootCallback* callback, void* arg) {
+ // Visit the primitive types, this is required since if there are no active verifiers they wont
+ // be in the entries array, and therefore not visited as roots.
+ if (primitive_initialized_) {
+ UndefinedType::GetInstance()->VisitRoots(callback, arg);
+ ConflictType::GetInstance()->VisitRoots(callback, arg);
+ BooleanType::GetInstance()->VisitRoots(callback, arg);
+ ByteType::GetInstance()->VisitRoots(callback, arg);
+ ShortType::GetInstance()->VisitRoots(callback, arg);
+ CharType::GetInstance()->VisitRoots(callback, arg);
+ IntegerType::GetInstance()->VisitRoots(callback, arg);
+ LongLoType::GetInstance()->VisitRoots(callback, arg);
+ LongHiType::GetInstance()->VisitRoots(callback, arg);
+ FloatType::GetInstance()->VisitRoots(callback, arg);
+ DoubleLoType::GetInstance()->VisitRoots(callback, arg);
+ DoubleHiType::GetInstance()->VisitRoots(callback, arg);
+ for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) {
+ small_precise_constants_[value - kMinSmallConstant]->VisitRoots(callback, arg);
+ }
+ }
+}
+
void RegTypeCache::VisitRoots(RootCallback* callback, void* arg) {
for (const RegType* entry : entries_) {
entry->VisitRoots(callback, arg);
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index eb17a52..29933cf 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -80,34 +80,34 @@
const BooleanType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *BooleanType::GetInstance();
}
- const ByteType& Byte() {
+ const RegType& Byte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *ByteType::GetInstance();
}
- const CharType& Char() {
+ const RegType& Char() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *CharType::GetInstance();
}
- const ShortType& Short() {
+ const RegType& Short() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *ShortType::GetInstance();
}
- const IntegerType& Integer() {
+ const RegType& Integer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *IntegerType::GetInstance();
}
- const FloatType& Float() {
+ const RegType& Float() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *FloatType::GetInstance();
}
- const LongLoType& LongLo() {
+ const RegType& LongLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *LongLoType::GetInstance();
}
- const LongHiType& LongHi() {
+ const RegType& LongHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *LongHiType::GetInstance();
}
- const DoubleLoType& DoubleLo() {
+ const RegType& DoubleLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *DoubleLoType::GetInstance();
}
- const DoubleHiType& DoubleHi() {
+ const RegType& DoubleHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *DoubleHiType::GetInstance();
}
- const UndefinedType& Undefined() {
+ const RegType& Undefined() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *UndefinedType::GetInstance();
}
const ConflictType& Conflict() {
@@ -138,6 +138,8 @@
const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void VisitStaticRoots(RootCallback* callback, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);