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.
Bug: 17262039
Change-Id: I592f2770570de97b431671cfbd409f63697892f1
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index d3641d1..637e3c9 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -127,7 +127,6 @@
if (concurrent) {
StartPreservingReferences(self);
}
-
soft_reference_queue_.ForwardSoftReferences(&PreserveSoftReferenceCallback,
&process_references_args_);
process_mark_stack_callback(arg);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4e2bfa0..17de883d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1145,6 +1145,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 8495ef2..1efe644 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4162,6 +4162,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 e63a90c..16229aa 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -217,6 +217,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 482bb4d..63fb2d9 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -588,6 +588,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_) {
+ Undefined().VisitRoots(callback, arg);
+ Conflict().VisitRoots(callback, arg);
+ Boolean().VisitRoots(callback, arg);
+ Byte().VisitRoots(callback, arg);
+ Short().VisitRoots(callback, arg);
+ Char().VisitRoots(callback, arg);
+ Integer().VisitRoots(callback, arg);
+ LongLo().VisitRoots(callback, arg);
+ LongHi().VisitRoots(callback, arg);
+ Float().VisitRoots(callback, arg);
+ DoubleLo().VisitRoots(callback, arg);
+ DoubleHi().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 (RegType* entry : entries_) {
entry->VisitRoots(callback, arg);
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index c0427eb..a75aaab 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -85,40 +85,40 @@
size_t GetCacheSize() {
return entries_.size();
}
- RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ static RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *BooleanType::GetInstance();
}
- RegType& Byte() {
+ static RegType& Byte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *ByteType::GetInstance();
}
- RegType& Char() {
+ static RegType& Char() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *CharType::GetInstance();
}
- RegType& Short() {
+ static RegType& Short() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *ShortType::GetInstance();
}
- RegType& Integer() {
+ static RegType& Integer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *IntegerType::GetInstance();
}
- RegType& Float() {
+ static RegType& Float() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *FloatType::GetInstance();
}
- RegType& LongLo() {
+ static RegType& LongLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *LongLoType::GetInstance();
}
- RegType& LongHi() {
+ static RegType& LongHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *LongHiType::GetInstance();
}
- RegType& DoubleLo() {
+ static RegType& DoubleLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *DoubleLoType::GetInstance();
}
- RegType& DoubleHi() {
+ static RegType& DoubleHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *DoubleHiType::GetInstance();
}
- RegType& Undefined() {
+ static RegType& Undefined() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *UndefinedType::GetInstance();
}
- RegType& Conflict() {
+ static RegType& Conflict() {
return *ConflictType::GetInstance();
}
RegType& JavaLangClass(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -146,6 +146,8 @@
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_);