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