diff options
| -rw-r--r-- | dex2oat/dex2oat.cc | 4 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 5 | ||||
| -rw-r--r-- | runtime/class_linker.h | 2 | ||||
| -rw-r--r-- | runtime/common_runtime_test.cc | 2 | ||||
| -rw-r--r-- | runtime/runtime.cc | 92 | ||||
| -rw-r--r-- | runtime/runtime.h | 2 | ||||
| -rw-r--r-- | runtime/thread.cc | 10 |
7 files changed, 79 insertions, 38 deletions
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 779128f924..1bd57ecfa7 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -2615,11 +2615,11 @@ class Dex2Oat FINAL { // 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 7b92ba41a5..38212dabba 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -864,8 +864,7 @@ void ClassLinker::FinishInit(Thread* self) { 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 @@ void ClassLinker::RunRootClinits() { 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 30c242399d..e4d9c96696 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -405,7 +405,7 @@ class ClassLinker { // 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 75b091d98f..be39631e44 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -182,7 +182,7 @@ void CommonRuntimeTestImpl::FinalizeSetup() { { 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 3b4d177646..fe959400f3 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -713,6 +713,23 @@ std::string Runtime::GetCompilerExecutable() const { 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 @@ bool Runtime::Start() { 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 @@ void Runtime::SetSentinel(mirror::Object* sentinel) { 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 */ false>(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 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { } 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 d85490c0a6..f413733804 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -212,6 +212,8 @@ class Runtime { 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 1a078d5fe6..19d9485f5e 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2045,15 +2045,15 @@ void Thread::FinishStartup() { // 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() { |