Merge "Revert^2 "Delay init of classes of pre-allocated exceptions.""
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index c9eb71d..8dca889 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2613,11 +2613,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 c219d3d..4a5da1f 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 f7674c8..a81c4d0 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() {