From dabeb3adf974d32ff1553af356d20e0a4abfd1f1 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Mon, 12 Jun 2017 17:10:07 -0700 Subject: Correctly set oat class status after initializing The previous CL had a bug where it would not set the oat class status for initialized classes that had run the class initializer for the boot image case. Aims to fix random dex2oat crashes during boot image creation. Bug: 62402160 Test: test-art-host Change-Id: Ia1814fc91ec71c9556eb37699a63be3b09ff6188 --- compiler/driver/compiler_driver.cc | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'compiler/driver/compiler_driver.cc') diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index cd1f466f0f..e03ddea85b 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2272,6 +2272,7 @@ class InitializeClassVisitor : public CompilationVisitor { const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_); ScopedObjectAccessUnchecked soa(Thread::Current()); StackHandleScope<3> hs(soa.Self()); + const bool is_boot_image = manager_->GetCompiler()->GetCompilerOptions().IsBootImage(); mirror::Class::Status old_status = klass->GetStatus();; // Only try to initialize classes that were successfully verified. @@ -2293,32 +2294,27 @@ class InitializeClassVisitor : public CompilationVisitor { ObjectLock lock(soa.Self(), h_klass); // Attempt to initialize allowing initialization of parent classes but still not static // fields. - bool is_superclass_initialized = true; - if (!manager_->GetCompiler()->GetCompilerOptions().IsAppImage()) { - // If not an app image case, the compiler won't initialize too much things and do a fast - // fail, don't check dependencies. - manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true); - } else { - // For app images, do the initialization recursively and resolve types encountered to make - // sure the compiler runs without error. - is_superclass_initialized = InitializeDependencies(klass, class_loader, soa.Self()); - if (is_superclass_initialized) { - manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true); - } - } + manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true); old_status = klass->GetStatus(); - // If superclass cannot be initialized, no need to proceed. + // If the class was not initialized, we can proceed to see if we can initialize static + // fields. if (!klass->IsInitialized() && - is_superclass_initialized && manager_->GetCompiler()->IsImageClass(descriptor)) { bool can_init_static_fields = false; - if (manager_->GetCompiler()->GetCompilerOptions().IsBootImage()) { + if (is_boot_image) { // We need to initialize static fields, we only do this for image classes that aren't - // marked with the $NoPreloadHolder (which implies this should not be initialized early). + // marked with the $NoPreloadHolder (which implies this should not be initialized + // early). can_init_static_fields = !StringPiece(descriptor).ends_with("$NoPreloadHolder;"); } else { - can_init_static_fields = manager_->GetCompiler()->GetCompilerOptions().IsAppImage() && + // The boot image case doesn't need to recursively initialize the dependencies with + // special logic since the class linker already does this. + bool is_superclass_initialized = + InitializeDependencies(klass, class_loader, soa.Self()); + can_init_static_fields = + manager_->GetCompiler()->GetCompilerOptions().IsAppImage() && !soa.Self()->IsExceptionPending() && + is_superclass_initialized && NoClinitInDependency(klass, soa.Self(), &class_loader); // TODO The checking for clinit can be removed since it's already // checked when init superclass. Currently keep it because it contains @@ -2361,6 +2357,10 @@ class InitializeClassVisitor : public CompilationVisitor { soa.Self()->ClearException(); transaction.Rollback(); CHECK_EQ(old_status, klass->GetStatus()) << "Previous class status not restored"; + } else if (is_boot_image) { + // For boot image, we want to put the updated status in the oat class since we can't + // reject the image anyways. + old_status = klass->GetStatus(); } } @@ -2370,6 +2370,8 @@ class InitializeClassVisitor : public CompilationVisitor { // above as we will allocate strings, so must be allowed to suspend. if (&klass->GetDexFile() == manager_->GetDexFile()) { InternStrings(klass, class_loader); + } else { + DCHECK(!is_boot_image) << "Boot image must have equal dex files"; } } } -- cgit v1.2.3-59-g8ed1b