ART: Clean up IRT-related abort messaging

Change AbortIfNoCheckJNI to take the abort message as a parameter.
This way it can be passed down.

Bug: 31893081
Test: m test-art-host
Change-Id: Ib24c7060f1b32c9613ab84e6c1966082c866bc14
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index f70503d..5cc1de2 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -36,21 +36,27 @@
     return false;
   }
   if (UNLIKELY(GetIndirectRefKind(iref) == kHandleScopeOrInvalid)) {
-    LOG(ERROR) << "JNI ERROR (app bug): invalid " << kind_ << " " << iref;
-    AbortIfNoCheckJNI();
+    AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): invalid %s %p",
+                                   GetIndirectRefKindString(kind_),
+                                   iref));
     return false;
   }
   const int topIndex = segment_state_.parts.topIndex;
   int idx = ExtractIndex(iref);
   if (UNLIKELY(idx >= topIndex)) {
-    LOG(ERROR) << "JNI ERROR (app bug): accessed stale " << kind_ << " "
-               << iref << " (index " << idx << " in a table of size " << topIndex << ")";
-    AbortIfNoCheckJNI();
+    std::string msg = StringPrintf(
+        "JNI ERROR (app bug): accessed stale %s %p  (index %d in a table of size %d)",
+        GetIndirectRefKindString(kind_),
+        iref,
+        idx,
+        topIndex);
+    AbortIfNoCheckJNI(msg);
     return false;
   }
   if (UNLIKELY(table_[idx].GetReference()->IsNull())) {
-    LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref;
-    AbortIfNoCheckJNI();
+    AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): accessed deleted %s %p",
+                                   GetIndirectRefKindString(kind_),
+                                   iref));
     return false;
   }
   if (UNLIKELY(!CheckEntry("use", iref, idx))) {
@@ -63,10 +69,13 @@
 inline bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const {
   IndirectRef checkRef = ToIndirectRef(idx);
   if (UNLIKELY(checkRef != iref)) {
-    LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what
-               << " stale " << kind_ << " " << iref
-               << " (should be " << checkRef << ")";
-    AbortIfNoCheckJNI();
+    std::string msg = StringPrintf(
+        "JNI ERROR (app bug): attempt to %s stale %s %p (should be %p)",
+        what,
+        GetIndirectRefKindString(kind_),
+        iref,
+        checkRef);
+    AbortIfNoCheckJNI(msg);
     return false;
   }
   return true;
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index 202e472..1eee7c4 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -32,6 +32,20 @@
 
 static constexpr bool kDumpStackOnNonLocalReference = false;
 
+const char* GetIndirectRefKindString(const IndirectRefKind& kind) {
+  switch (kind) {
+    case kHandleScopeOrInvalid:
+      return "HandleScopeOrInvalid";
+    case kLocal:
+      return "Local";
+    case kGlobal:
+      return "Global";
+    case kWeakGlobal:
+      return "WeakGlobal";
+  }
+  return "IndirectRefKind Error";
+}
+
 template<typename T>
 class MutatorLockedDumpable {
  public:
@@ -58,12 +72,14 @@
   return os;
 }
 
-void IndirectReferenceTable::AbortIfNoCheckJNI() {
+void IndirectReferenceTable::AbortIfNoCheckJNI(const std::string& msg) {
   // If -Xcheck:jni is on, it'll give a more detailed error before aborting.
   JavaVMExt* vm = Runtime::Current()->GetJavaVM();
   if (!vm->IsCheckJniEnabled()) {
     // Otherwise, we want to abort rather than hand back a bad reference.
-    LOG(FATAL) << "JNI ERROR (app bug): see above.";
+    LOG(FATAL) << msg;
+  } else {
+    LOG(ERROR) << msg;
   }
 }
 
@@ -113,9 +129,15 @@
   DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);
 
   if (topIndex == max_entries_) {
-    LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow "
-               << "(max=" << max_entries_ << ")\n"
-               << MutatorLockedDumpable<IndirectReferenceTable>(*this);
+    std::ostringstream oss;
+    oss << "JNI ERROR (app bug): " << kind_ << " table overflow "
+        << "(max=" << max_entries_ << ")\n"
+        << MutatorLockedDumpable<IndirectReferenceTable>(*this);
+    if (VLOG_IS_ON(jni)) {
+      LOG(FATAL) << oss.str();
+    } else {
+      LOG_FATAL_THIS_THREAD_ONLY(oss.str());
+    }
   }
 
   // We know there's enough room in the table.  Now we just need to find
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index 13c6225..e194f79 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -119,6 +119,7 @@
   kWeakGlobal    = 3   // <<weak global reference>>
 };
 std::ostream& operator<<(std::ostream& os, const IndirectRefKind& rhs);
+const char* GetIndirectRefKindString(const IndirectRefKind& kind);
 
 /*
  * Determine what kind of indirect reference this is.
@@ -372,8 +373,8 @@
     return reinterpret_cast<IndirectRef>(uref);
   }
 
-  // Abort if check_jni is not enabled.
-  static void AbortIfNoCheckJNI();
+  // Abort if check_jni is not enabled. Otherwise, just log as an error.
+  static void AbortIfNoCheckJNI(const std::string& msg);
 
   /* extra debugging checks */
   bool GetChecked(IndirectRef) const;