Don't compile boot image if the process is not Zygote.

For other processes, in-memory compilation is not useful and probably
fails because they don't have the permission to invoke dex2oat.

Also added a runtime option "-Xallowinmemorycompilation". This can be
used by tests which are not Zygote but examines in-memory compilation.

Bug: 247055146
Test: m test-art-host-gtest-art_dex2oat_tests
Test: ArtGtestsTargetChroot
Change-Id: I179885ffd528ca6836bcba5006eaac6255e7f6ec
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 2978fb4..4518905 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -431,6 +431,7 @@
                                                 relocate,
                                                 /*executable=*/ true,
                                                 /*extra_reservation_size=*/ 0u,
+                                                /*allow_in_memory_compilation=*/ true,
                                                 &boot_image_spaces,
                                                 &extra_reservation);
   };
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index dbe9161..2083d4b 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -483,6 +483,7 @@
                                        runtime->ShouldRelocate(),
                                        /*executable=*/ !runtime->IsAotCompiler(),
                                        heap_reservation_size,
+                                       runtime->AllowInMemoryCompilation(),
                                        &boot_image_spaces,
                                        &heap_reservation)) {
     DCHECK_EQ(heap_reservation_size, heap_reservation.IsValid() ? heap_reservation.Size() : 0u);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 00b4f47..ac0d937 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -2168,6 +2168,7 @@
   bool HasSystem() const { return has_system_; }
 
   bool LoadFromSystem(size_t extra_reservation_size,
+                      bool allow_in_memory_compilation,
                       /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
                       /*out*/MemMap* extra_reservation,
                       /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -3126,6 +3127,7 @@
 
 bool ImageSpace::BootImageLoader::LoadFromSystem(
     size_t extra_reservation_size,
+    bool allow_in_memory_compilation,
     /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
     /*out*/MemMap* extra_reservation,
     /*out*/std::string* error_msg) {
@@ -3138,7 +3140,7 @@
                          boot_class_path_image_fds_,
                          boot_class_path_vdex_fds_,
                          boot_class_path_oat_fds_);
-  if (!layout.LoadFromSystem(image_isa_, /*allow_in_memory_compilation=*/true, error_msg)) {
+  if (!layout.LoadFromSystem(image_isa_, allow_in_memory_compilation, error_msg)) {
     return false;
   }
 
@@ -3201,6 +3203,7 @@
     bool relocate,
     bool executable,
     size_t extra_reservation_size,
+    bool allow_in_memory_compilation,
     /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
     /*out*/MemMap* extra_reservation) {
   ScopedTrace trace(__FUNCTION__);
@@ -3231,8 +3234,11 @@
   std::vector<std::string> error_msgs;
 
   std::string error_msg;
-  if (loader.LoadFromSystem(
-          extra_reservation_size, boot_image_spaces, extra_reservation, &error_msg)) {
+  if (loader.LoadFromSystem(extra_reservation_size,
+                            allow_in_memory_compilation,
+                            boot_image_spaces,
+                            extra_reservation,
+                            &error_msg)) {
     return true;
   }
   error_msgs.push_back(error_msg);
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 472ae40..58030de 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -144,6 +144,7 @@
       bool relocate,
       bool executable,
       size_t extra_reservation_size,
+      bool allow_in_memory_compilation,
       /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
       /*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);
 
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index b3a5917..b85560c 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -145,6 +145,7 @@
                                      /*relocate=*/ false,
                                      /*executable=*/ true,
                                      /*extra_reservation_size=*/ 0u,
+                                     /*allow_in_memory_compilation=*/ false,
                                      &boot_image_spaces,
                                      &extra_reservation);
   };
@@ -330,6 +331,7 @@
     options->emplace_back(android::base::StringPrintf("-Ximage:%s", image_location.c_str()),
                           nullptr);
     options->emplace_back(kRelocate ? "-Xrelocate" : "-Xnorelocate", nullptr);
+    options->emplace_back("-Xallowinmemorycompilation", nullptr);
 
     // We want to test the relocation behavior of ImageSpace. As such, don't pretend we're a
     // compiler.
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 0450e3e..6d4a0be 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -183,6 +183,10 @@
           .IntoKey(M::Image)
       .Define("-Xforcejitzygote")
           .IntoKey(M::ForceJitZygote)
+      .Define("-Xallowinmemorycompilation")
+          .WithHelp("Allows compiling the boot classpath in memory when the given boot image is"
+              "unusable. This option is set by default for Zygote.")
+          .IntoKey(M::AllowInMemoryCompilation)
       .Define("-Xprimaryzygote")
           .IntoKey(M::PrimaryZygote)
       .Define("-Xbootclasspath-locations:_")
@@ -735,6 +739,10 @@
     args.Set(M::Image, ParseStringList<':'>::Split(GetJitZygoteBootImageLocation()));
   }
 
+  if (args.Exists(M::Zygote)) {
+    args.Set(M::AllowInMemoryCompilation, Unit());
+  }
+
   if (!args.Exists(M::CompilerCallbacksPtr) && !args.Exists(M::Image)) {
     const bool deny_art_apex_data_files = args.Exists(M::DenyArtApexDataFiles);
     std::string image_locations =
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1f613c7..ac2bc54 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1527,6 +1527,7 @@
   is_explicit_gc_disabled_ = runtime_options.Exists(Opt::DisableExplicitGC);
   image_dex2oat_enabled_ = runtime_options.GetOrDefault(Opt::ImageDex2Oat);
   dump_native_stack_on_sig_quit_ = runtime_options.GetOrDefault(Opt::DumpNativeStackOnSigQuit);
+  allow_in_memory_compilation_ = runtime_options.Exists(Opt::AllowInMemoryCompilation);
 
   if (is_zygote_ || runtime_options.Exists(Opt::OnlyUseTrustedOatFiles)) {
     oat_file_manager_->SetOnlyUseTrustedOatFiles();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 3cc689e..42c5235 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -1125,6 +1125,8 @@
   // jars, which is encoded into .oat files.
   static std::string GetApexVersions(ArrayRef<const std::string> boot_class_path_locations);
 
+  bool AllowInMemoryCompilation() const { return allow_in_memory_compilation_; }
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -1479,6 +1481,9 @@
   // True if files in /data/misc/apexdata/com.android.art are considered untrustworthy.
   bool deny_art_apex_data_files_;
 
+  // Whether to allow compiling the boot classpath in memory when the given boot image is unusable.
+  bool allow_in_memory_compilation_ = false;
+
   // Saved environment.
   class EnvSnapshot {
    public:
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 6721834..769ed04 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -47,6 +47,7 @@
 RUNTIME_OPTIONS_KEY (std::string,         ClassPath)
 RUNTIME_OPTIONS_KEY (ParseStringList<':'>,Image)
 RUNTIME_OPTIONS_KEY (Unit,                ForceJitZygote)
+RUNTIME_OPTIONS_KEY (Unit,                AllowInMemoryCompilation)
 RUNTIME_OPTIONS_KEY (Unit,                CheckJni)
 RUNTIME_OPTIONS_KEY (Unit,                JniOptsForceCopy)
 RUNTIME_OPTIONS_KEY (std::string,         JdwpOptions,                    "suspend=n,server=y")