ART: Initialize intrinsics earlier.

The reasons previously described in `Runtime::Start()` for
initializing intrinsics after well-known classes no longer
hold. And if we want to add some new well-known classes and
initialize them early, we actually need to initialize
intrinsics earlier. For example, the class initializer for
`jdk.internal.math.FloatDecimal` requires intrinsics to be
initialized when using the `invoke-polymorphic` instruction.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 19575890
Change-Id: I7a119a7dcef0f5263b89f22cf45f2b45725d0eee
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index fa15e53..f2e0a6e 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2753,6 +2753,7 @@
 
     Thread* self = Thread::Current();
     runtime_->GetClassLinker()->RunEarlyRootClinits(self);
+    InitializeIntrinsics();
     WellKnownClasses::Init(self->GetJniEnv());
     runtime_->RunRootClinits(self);
 
@@ -2760,12 +2761,6 @@
     // Runtime::Start, give it away now so that we don't starve GC.
     self->TransitionFromRunnableToSuspended(ThreadState::kNative);
 
-    // Now that we are in native state, initialize well known classes and
-    // intrinsics if we don't have a boot image.
-    if (IsBootImage() || runtime_->GetHeap()->GetBootImageSpaces().empty()) {
-      InitializeIntrinsics();
-    }
-
     WatchDog::SetRuntime(runtime_.get());
 
     return true;
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 3589769..1e066b1 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -159,14 +159,11 @@
   {
     ScopedObjectAccess soa(Thread::Current());
     runtime_->GetClassLinker()->RunEarlyRootClinits(soa.Self());
+    InitializeIntrinsics();
     WellKnownClasses::Init(Thread::Current()->GetJniEnv());
     runtime_->RunRootClinits(soa.Self());
   }
 
-  // We're back in native, take the opportunity to initialize well known classes and ensure
-  // intrinsics are initialized.
-  InitializeIntrinsics();
-
   runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
   // Reduce timinig-dependent flakiness in OOME behavior (eg StubTest.AllocObject).
   runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index a82fddc..dfda20a 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -62,11 +62,6 @@
 
 class UnstartedRuntimeTest : public CommonRuntimeTest {
  protected:
-  void SetUp() override {
-    CommonRuntimeTest::SetUp();
-    InitializeIntrinsics();
-  }
-
   // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
   // test friends.
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index b38b2cb..023ba10 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -961,6 +961,7 @@
   started_ = true;
 
   class_linker_->RunEarlyRootClinits(self);
+  InitializeIntrinsics();
 
   self->TransitionFromRunnableToSuspended(ThreadState::kNative);
 
@@ -971,11 +972,6 @@
     InitNativeMethods();
   }
 
-  // IntializeIntrinsics needs to be called after the WellKnownClasses::Init in InitNativeMethods
-  // because in checking the invocation types of intrinsic methods ArtMethod::GetInvokeType()
-  // needs the SignaturePolymorphic annotation class which is initialized in WellKnownClasses::Init.
-  InitializeIntrinsics();
-
   // InitializeCorePlatformApiPrivateFields() needs to be called after well known class
   // initializtion in InitNativeMethods().
   art::hiddenapi::InitializeCorePlatformApiPrivateFields();
diff --git a/runtime/runtime_intrinsics.cc b/runtime/runtime_intrinsics.cc
index 1672c49..fb60cfe 100644
--- a/runtime/runtime_intrinsics.cc
+++ b/runtime/runtime_intrinsics.cc
@@ -90,10 +90,10 @@
   }
 }
 
-bool AreAllIntrinsicsInitialized() {
-  ScopedObjectAccess soa(Thread::Current());
+bool AreAllIntrinsicsInitialized() REQUIRES_SHARED(Locks::mutator_lock_) {
+  Thread* self = Thread::Current();
 #define IS_INTRINSIC_INITIALIZED(Name, InvokeType, _, __, ___, ClassName, MethodName, Signature) \
-  IsIntrinsicInitialized(soa.Self(),                                                             \
+  IsIntrinsicInitialized(self,                                                                   \
                          Intrinsics::k##Name,                                                    \
                          InvokeType,                                                             \
                          ClassName,                                                              \
@@ -107,11 +107,11 @@
 }  // namespace
 
 void InitializeIntrinsics() {
-  ScopedObjectAccess soa(Thread::Current());
+  Thread* self = Thread::Current();
   // Initialization here uses the short-circuit operator || to stop
   // initializing if there's an already initialized intrinsic.
 #define INITIALIZE_INTRINSIC(Name, InvokeType, _, __, ___, ClassName, MethodName, Signature) \
-  InitializeIntrinsic(soa.Self(),                                                            \
+  InitializeIntrinsic(self,                                                                  \
                       Intrinsics::k##Name,                                                   \
                       InvokeType,                                                            \
                       ClassName,                                                             \
diff --git a/runtime/runtime_intrinsics.h b/runtime/runtime_intrinsics.h
index 98dc9bc..bf2cb2b 100644
--- a/runtime/runtime_intrinsics.h
+++ b/runtime/runtime_intrinsics.h
@@ -17,9 +17,11 @@
 #ifndef ART_RUNTIME_RUNTIME_INTRINSICS_H_
 #define ART_RUNTIME_RUNTIME_INTRINSICS_H_
 
+#include "base/locks.h"
+
 namespace art {
 
-void InitializeIntrinsics();
+void InitializeIntrinsics() REQUIRES_SHARED(Locks::mutator_lock_);
 
 }  // namespace art