Log unmarked strongly interned string in SweepInterpreterCache()
Bug: 275005060
Test: manual
Change-Id: I180879ed99170cab4ddc21cd7ffc23c97d31f610
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index c274fed..888c38a 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -161,6 +161,10 @@
REQUIRES_SHARED(Locks::mutator_lock_);
void AssertNoThreadMarkStackMapping(Thread* thread) REQUIRES(!mark_stack_lock_);
+ // Dump information about reference `ref` and return it as a string.
+ // Use `ref_name` to name the reference in messages. Each message is prefixed with `indent`.
+ std::string DumpReferenceInfo(mirror::Object* ref, const char* ref_name, const char* indent = "")
+ REQUIRES_SHARED(Locks::mutator_lock_);
private:
void PushOntoMarkStack(Thread* const self, mirror::Object* obj)
@@ -282,10 +286,6 @@
void ComputeUnevacFromSpaceLiveRatio();
void LogFromSpaceRefHolder(mirror::Object* obj, MemberOffset offset)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Dump information about reference `ref` and return it as a string.
- // Use `ref_name` to name the reference in messages. Each message is prefixed with `indent`.
- std::string DumpReferenceInfo(mirror::Object* ref, const char* ref_name, const char* indent = "")
- REQUIRES_SHARED(Locks::mutator_lock_);
// Dump information about heap reference `ref`, referenced from object `obj` at offset `offset`,
// and return it as a string.
std::string DumpHeapReference(mirror::Object* obj, MemberOffset offset, mirror::Object* ref)
diff --git a/runtime/thread.cc b/runtime/thread.cc
index a341c56..335b365 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -77,6 +77,7 @@
#include "handle_scope-inl.h"
#include "indirect_reference_table-inl.h"
#include "instrumentation.h"
+#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "interpreter/shadow_frame-inl.h"
#include "java_frame_root_info.h"
@@ -4476,8 +4477,28 @@
mirror::Object* new_object = visitor->IsMarked(object);
// We know the string is marked because it's a strongly-interned string that
// is always alive (see b/117621117 for trying to make those strings weak).
- CHECK_NE(new_object, nullptr) << "old-string:" << object;
- if (new_object != object) {
+ if (new_object == nullptr) {
+ // (b/275005060) Currently the problem is reported only on CC GC.
+ // Therefore we log it with more information. But since the failure rate
+ // is quite high, sampling it.
+ if (gUseReadBarrier) {
+ static constexpr size_t kSampleRate = 5;
+ if (MilliTime() % kSampleRate == 0) {
+ Runtime* runtime = Runtime::Current();
+ gc::collector::ConcurrentCopying* cc = runtime->GetHeap()->ConcurrentCopyingCollector();
+ CHECK_NE(cc, nullptr);
+ LOG(FATAL) << cc->DumpReferenceInfo(object, "string")
+ << " string interned: " << std::boolalpha
+ << runtime->GetInternTable()->LookupStrong(
+ Thread::Current(), down_cast<mirror::String*>(object))
+ << std::noboolalpha;
+ }
+ } else {
+ // Other GCs
+ LOG(FATAL) << __FUNCTION__
+ << ": IsMarked returned null for a strongly interned string: " << object;
+ }
+ } else if (new_object != object) {
*value = reinterpret_cast<size_t>(new_object);
}
return;