Revert^2 "Delay init of classes of pre-allocated exceptions."

This reverts commit 29cf32bb64dc61c4f755661939630775bd36419d.

Fixed heap-poisoning/gcstress tests by calling the Alloc<>()
of the exception object with kInstrumented=true.

Change-Id: I209ab4f020e9c6fb67319fddde69ed87e3653223
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: Pixel 2 XL boots.
Test: run_build_test_target.py art-gtest-heap-poisoning
Test: run_build_test_target.py art-interpreter-gcstress
Bug: 109925024
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 3b4d177..ad70bdc 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -713,6 +713,23 @@
   return compiler_executable;
 }
 
+void Runtime::RunRootClinits(Thread* self) {
+  class_linker_->RunRootClinits(self);
+
+  GcRoot<mirror::Throwable>* exceptions[] = {
+      &pre_allocated_OutOfMemoryError_when_throwing_exception_,
+      // &pre_allocated_OutOfMemoryError_when_throwing_oome_,             // Same class as above.
+      // &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,   // Same class as above.
+      &pre_allocated_NoClassDefFoundError_,
+  };
+  for (GcRoot<mirror::Throwable>* exception : exceptions) {
+    StackHandleScope<1> hs(self);
+    Handle<mirror::Class> klass = hs.NewHandle<mirror::Class>(exception->Read()->GetClass());
+    class_linker_->EnsureInitialized(self, klass, true, true);
+    self->AssertNoPendingException();
+  }
+}
+
 bool Runtime::Start() {
   VLOG(startup) << "Runtime::Start entering";
 
@@ -742,8 +759,10 @@
     auto field_class(hs.NewHandle<mirror::Class>(GetClassRoot<mirror::Field>(class_roots)));
 
     class_linker_->EnsureInitialized(soa.Self(), class_class, true, true);
+    self->AssertNoPendingException();
     // Field class is needed for register_java_net_InetAddress in libcore, b/28153851.
     class_linker_->EnsureInitialized(soa.Self(), field_class, true, true);
+    self->AssertNoPendingException();
   }
 
   // InitNativeMethods needs to be after started_ so that the classes
@@ -1090,15 +1109,30 @@
   sentinel_ = GcRoot<mirror::Object>(sentinel);
 }
 
-static inline void InitPreAllocatedException(Thread* self,
-                                             GcRoot<mirror::Throwable>* exception,
-                                             const char* exception_class_descriptor,
-                                             const char* msg)
+static inline void CreatePreAllocatedException(Thread* self,
+                                               Runtime* runtime,
+                                               GcRoot<mirror::Throwable>* exception,
+                                               const char* exception_class_descriptor,
+                                               const char* msg)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK_EQ(self, Thread::Current());
-  self->ThrowNewException(exception_class_descriptor, msg);
-  *exception = GcRoot<mirror::Throwable>(self->GetException());
-  self->ClearException();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  // Allocate an object without initializing the class to allow non-trivial Throwable.<clinit>().
+  ObjPtr<mirror::Class> klass = class_linker->FindSystemClass(self, exception_class_descriptor);
+  CHECK(klass != nullptr);
+  gc::AllocatorType allocator_type = runtime->GetHeap()->GetCurrentAllocator();
+  ObjPtr<mirror::Throwable> exception_object = ObjPtr<mirror::Throwable>::DownCast(
+      klass->Alloc</* kIsInstrumented */ true>(self, allocator_type));
+  CHECK(exception_object != nullptr);
+  *exception = GcRoot<mirror::Throwable>(exception_object);
+  // Initialize the "detailMessage" field.
+  ObjPtr<mirror::String> message = mirror::String::AllocFromModifiedUtf8(self, msg);
+  CHECK(message != nullptr);
+  ObjPtr<mirror::Class> throwable = GetClassRoot<mirror::Throwable>(class_linker);
+  ArtField* detailMessageField =
+      throwable->FindDeclaredInstanceField("detailMessage", "Ljava/lang/String;");
+  CHECK(detailMessageField != nullptr);
+  detailMessageField->SetObject</* kTransactionActive */ false>(exception->Read(), message);
 }
 
 bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
@@ -1543,32 +1577,36 @@
   } else {
     // Pre-allocate an OutOfMemoryError for the case when we fail to
     // allocate the exception to be thrown.
-    InitPreAllocatedException(self,
-                              &pre_allocated_OutOfMemoryError_when_throwing_exception_,
-                              "Ljava/lang/OutOfMemoryError;",
-                              "OutOfMemoryError thrown while trying to throw an exception; "
-                              "no stack trace available");
+    CreatePreAllocatedException(self,
+                                this,
+                                &pre_allocated_OutOfMemoryError_when_throwing_exception_,
+                                "Ljava/lang/OutOfMemoryError;",
+                                "OutOfMemoryError thrown while trying to throw an exception; "
+                                    "no stack trace available");
     // Pre-allocate an OutOfMemoryError for the double-OOME case.
-    InitPreAllocatedException(self,
-                              &pre_allocated_OutOfMemoryError_when_throwing_oome_,
-                              "Ljava/lang/OutOfMemoryError;",
-                              "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
-                              "no stack trace available");
+    CreatePreAllocatedException(self,
+                                this,
+                                &pre_allocated_OutOfMemoryError_when_throwing_oome_,
+                                "Ljava/lang/OutOfMemoryError;",
+                                "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
+                                    "no stack trace available");
     // Pre-allocate an OutOfMemoryError for the case when we fail to
     // allocate while handling a stack overflow.
-    InitPreAllocatedException(self,
-                              &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
-                              "Ljava/lang/OutOfMemoryError;",
-                              "OutOfMemoryError thrown while trying to handle a stack overflow; "
-                              "no stack trace available");
+    CreatePreAllocatedException(self,
+                                this,
+                                &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
+                                "Ljava/lang/OutOfMemoryError;",
+                                "OutOfMemoryError thrown while trying to handle a stack overflow; "
+                                    "no stack trace available");
 
     // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class
     // ahead of checking the application's class loader.
-    InitPreAllocatedException(self,
-                              &pre_allocated_NoClassDefFoundError_,
-                              "Ljava/lang/NoClassDefFoundError;",
-                              "Class not found using the boot class loader; "
-                              "no stack trace available");
+    CreatePreAllocatedException(self,
+                                this,
+                                &pre_allocated_NoClassDefFoundError_,
+                                "Ljava/lang/NoClassDefFoundError;",
+                                "Class not found using the boot class loader; "
+                                    "no stack trace available");
   }
 
   // Runtime initialization is largely done now.