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/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index be3f922..ec5e806 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2619,11 +2619,11 @@
     // set up.
     interpreter::UnstartedRuntime::Initialize();
 
-    runtime_->GetClassLinker()->RunRootClinits();
+    Thread* self = Thread::Current();
+    runtime_->RunRootClinits(self);
 
     // Runtime::Create acquired the mutator_lock_ that is normally given away when we
     // Runtime::Start, give it away now so that we don't starve GC.
-    Thread* self = Thread::Current();
     self->TransitionFromRunnableToSuspended(kNative);
 
     return true;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7b92ba4..38212da 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -864,8 +864,7 @@
   VLOG(startup) << "ClassLinker::FinishInit exiting";
 }
 
-void ClassLinker::RunRootClinits() {
-  Thread* self = Thread::Current();
+void ClassLinker::RunRootClinits(Thread* self) {
   for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); ++i) {
     ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i), this);
     if (!c->IsArrayClass() && !c->IsPrimitive()) {
@@ -873,6 +872,8 @@
       Handle<mirror::Class> h_class(hs.NewHandle(c));
       EnsureInitialized(self, h_class, true, true);
       self->AssertNoPendingException();
+    } else {
+      DCHECK(c->IsInitialized());
     }
   }
 }
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 30c2423..e4d9c96 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -405,7 +405,7 @@
 
   // Initializes classes that have instances in the image but that have
   // <clinit> methods so they could not be initialized by the compiler.
-  void RunRootClinits()
+  void RunRootClinits(Thread* self)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
 
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 75b091d..be39631 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -182,7 +182,7 @@
 
   {
     ScopedObjectAccess soa(Thread::Current());
-    class_linker_->RunRootClinits();
+    runtime_->RunRootClinits(soa.Self());
   }
 
   // We're back in native, take the opportunity to initialize well known classes.
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.
diff --git a/runtime/runtime.h b/runtime/runtime.h
index d85490c..f413733 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -212,6 +212,8 @@
     return finished_starting_;
   }
 
+  void RunRootClinits(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+
   static Runtime* Current() {
     return instance_;
   }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 1a078d5..19d9485 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2045,15 +2045,15 @@
 
   // Finish attaching the main thread.
   ScopedObjectAccess soa(Thread::Current());
-  Thread::Current()->CreatePeer("main", false, runtime->GetMainThreadGroup());
-  Thread::Current()->AssertNoPendingException();
+  soa.Self()->CreatePeer("main", false, runtime->GetMainThreadGroup());
+  soa.Self()->AssertNoPendingException();
 
-  Runtime::Current()->GetClassLinker()->RunRootClinits();
+  runtime->RunRootClinits(soa.Self());
 
   // The thread counts as started from now on. We need to add it to the ThreadGroup. For regular
   // threads, this is done in Thread.start() on the Java side.
-  Thread::Current()->NotifyThreadGroup(soa, runtime->GetMainThreadGroup());
-  Thread::Current()->AssertNoPendingException();
+  soa.Self()->NotifyThreadGroup(soa, runtime->GetMainThreadGroup());
+  soa.Self()->AssertNoPendingException();
 }
 
 void Thread::Shutdown() {