Add option for controling app image class initialization

The new option is --initialize-app-image-classes. This attempts to
initialize app image classes by running the class initializers ahead
of time.

Will test this through test 660, but there are currently aborts when
it's enabled.

Test: test-art-host
Bug: 70735003

Change-Id: Icc05683b23098a15531097f67aad17144f0badaf
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 6a7def8..8d09977 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -76,6 +76,7 @@
       deduplicate_code_(true),
       count_hotness_in_compiled_code_(false),
       resolve_startup_const_strings_(false),
+      initialize_app_image_classes_(false),
       check_profiled_methods_(ProfileMethodsCheck::kNone),
       max_image_block_size_(std::numeric_limits<uint32_t>::max()),
       register_allocation_strategy_(RegisterAllocator::kRegisterAllocatorDefault),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index bd832b9..98b15dc 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -346,6 +346,10 @@
     max_image_block_size_ = size;
   }
 
+  bool InitializeAppImageClasses() const {
+    return initialize_app_image_classes_;
+  }
+
   // Is `boot_image_filename` the name of a core image (small boot
   // image used for ART testing only)?
   static bool IsCoreImageFilename(const std::string& boot_image_filename);
@@ -429,6 +433,9 @@
   // profile.
   bool resolve_startup_const_strings_;
 
+  // Whether we attempt to run class initializers for app image classes.
+  bool initialize_app_image_classes_;
+
   // When running profile-guided compilation, check that methods intended to be compiled end
   // up compiled and are not punted.
   ProfileMethodsCheck check_profiled_methods_;
diff --git a/compiler/driver/compiler_options_map-inl.h b/compiler/driver/compiler_options_map-inl.h
index aebde10..e8a425d 100644
--- a/compiler/driver/compiler_options_map-inl.h
+++ b/compiler/driver/compiler_options_map-inl.h
@@ -79,6 +79,7 @@
     options->count_hotness_in_compiled_code_ = true;
   }
   map.AssignIfExists(Base::ResolveStartupConstStrings, &options->resolve_startup_const_strings_);
+  map.AssignIfExists(Base::InitializeAppImageClasses, &options->initialize_app_image_classes_);
   if (map.Exists(Base::CheckProfiledMethods)) {
     options->check_profiled_methods_ = *map.Get(Base::CheckProfiledMethods);
   }
@@ -192,6 +193,11 @@
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(Map::ResolveStartupConstStrings)
 
+      .Define("--initialize-app-image-classes=_")
+          .template WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(Map::InitializeAppImageClasses)
+
       .Define("--verbose-methods=_")
           .template WithType<ParseStringList<','>>()
           .IntoKey(Map::VerboseMethods)
diff --git a/compiler/driver/compiler_options_map.def b/compiler/driver/compiler_options_map.def
index 1a58f8d..df06bd8 100644
--- a/compiler/driver/compiler_options_map.def
+++ b/compiler/driver/compiler_options_map.def
@@ -51,6 +51,7 @@
 COMPILER_OPTIONS_KEY (bool,                        AbortOnHardVerifierFailure)
 COMPILER_OPTIONS_KEY (bool,                        AbortOnSoftVerifierFailure)
 COMPILER_OPTIONS_KEY (bool,                        ResolveStartupConstStrings, false)
+COMPILER_OPTIONS_KEY (bool,                        InitializeAppImageClasses, false)
 COMPILER_OPTIONS_KEY (std::string,                 DumpInitFailures)
 COMPILER_OPTIONS_KEY (std::string,                 DumpCFG)
 COMPILER_OPTIONS_KEY (Unit,                        DumpCFGAppend)
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 8893d67..b4cd5d7 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -2186,7 +2186,8 @@
                 ClassLinker::kAppImageMayContainStrings &&
                 !soa.Self()->IsExceptionPending() &&
                 is_superclass_initialized &&
-                NoClinitInDependency(klass, soa.Self(), &class_loader);
+                (manager_->GetCompiler()->GetCompilerOptions().InitializeAppImageClasses() ||
+                 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
             // processing of intern strings. Will be removed later when intern strings