Check the to-space invariant on a delivered exception.

Test: art/test/testrunner/testrunner.py
Bug: 62339341
Bug: 12687968
Change-Id: Ida5e91031cd94429a72fcc9d4d1333d21dd07421
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index d8b6237..f94923e 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -166,10 +166,9 @@
                 << line_number << ")";
     }
   }
-  if (clear_exception_) {
-    // Exception was cleared as part of delivery.
-    DCHECK(!self_->IsExceptionPending());
-  } else {
+  // Exception was cleared as part of delivery.
+  DCHECK(!self_->IsExceptionPending());
+  if (!clear_exception_) {
     // Put exception back in root set with clear throw location.
     self_->SetException(exception_ref.Get());
   }
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index 8090f9b..12b63c9 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -112,6 +112,10 @@
     handler_dex_pc_ = dex_pc;
   }
 
+  bool GetClearException() const {
+    return clear_exception_;
+  }
+
   void SetClearException(bool clear_exception) {
     clear_exception_ = clear_exception;
   }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 968a23b..2412931 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3080,6 +3080,10 @@
     UNREACHABLE();
   }
 
+  if (kUseReadBarrier) {
+    ReadBarrier::AssertToSpaceInvariant(exception.Ptr());
+  }
+
   // This is a real exception: let the instrumentation know about it.
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
   if (instrumentation->HasExceptionThrownListeners() &&
@@ -3121,6 +3125,18 @@
   QuickExceptionHandler exception_handler(this, false);
   exception_handler.FindCatch(exception);
   exception_handler.UpdateInstrumentationStack();
+  if (exception_handler.GetClearException()) {
+    // Exception was cleared as part of delivery.
+    DCHECK(!IsExceptionPending());
+  } else {
+    // Exception was put back with a throw location.
+    DCHECK(IsExceptionPending());
+    if (kUseReadBarrier) {
+      // Check the to-space invariant on the re-installed exception.
+      ObjPtr<mirror::Throwable> reinstalled_exception = GetException();
+      ReadBarrier::AssertToSpaceInvariant(reinstalled_exception.Ptr());
+    }
+  }
   exception_handler.DoLongJump();
 }