Make the notification of JIT zygote completion its own task.

Now that we are compiling two boot image in memory (because there are
two profiles), we were creating two tasks that were doing the same
thing. The JIT only expects one execution of the task, so make the
reporting its own task.

Test: boot with JIT zygote
Bug: 220702556
Bug: 221093821
Change-Id: I434284f9acc0f99fa90e1821071b2736031d2504
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index cb98830..685e707 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -836,12 +836,6 @@
         }
       }
     }
-
-    if (Runtime::Current()->IsZygote()) {
-      // Record that we are done compiling the profile.
-      Runtime::Current()->GetJit()->GetCodeCache()->GetZygoteMap()->SetCompilationState(
-          ZygoteCompilationState::kDone);
-    }
   }
 
  private:
@@ -850,6 +844,20 @@
   DISALLOW_COPY_AND_ASSIGN(JitDoneCompilingProfileTask);
 };
 
+class JitZygoteDoneCompilingTask final : public SelfDeletingTask {
+ public:
+  JitZygoteDoneCompilingTask() {}
+
+  void Run(Thread* self ATTRIBUTE_UNUSED) override {
+    DCHECK(Runtime::Current()->IsZygote());
+    Runtime::Current()->GetJit()->GetCodeCache()->GetZygoteMap()->SetCompilationState(
+        ZygoteCompilationState::kDone);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(JitZygoteDoneCompilingTask);
+};
+
 /**
  * A JIT task to run Java verification of boot classpath classes that were not
  * verified at compile-time.
@@ -941,6 +949,8 @@
         added_to_queue += runtime->GetJit()->CompileMethodsFromProfile(
             self, boot_class_path, profile_file, null_handle, /* add_to_queue= */ true);
       }
+      DCHECK(runtime->GetJit()->InZygoteUsingJit());
+      runtime->GetJit()->AddPostBootTask(self, new JitZygoteDoneCompilingTask());
     }
 
     JitCodeCache* code_cache = runtime->GetJit()->GetCodeCache();
@@ -1322,14 +1332,10 @@
       Task* task = new JitCompileTask(
           method, JitCompileTask::TaskKind::kPreCompile, CompilationKind::kOptimized);
       if (compile_after_boot) {
-        MutexLock mu(Thread::Current(), boot_completed_lock_);
-        if (!boot_completed_) {
-          tasks_after_boot_.push_back(task);
-          return true;
-        }
-        DCHECK(tasks_after_boot_.empty());
+        AddPostBootTask(self, task);
+      } else {
+        thread_pool_->AddTask(self, task);
       }
-      thread_pool_->AddTask(self, task);
       return true;
     }
   }
@@ -1438,14 +1444,7 @@
   }
 
   // Add a task to run when all compilation is done.
-  JitDoneCompilingProfileTask* task = new JitDoneCompilingProfileTask(dex_files);
-  MutexLock mu(Thread::Current(), boot_completed_lock_);
-  if (!boot_completed_) {
-    tasks_after_boot_.push_back(task);
-  } else {
-    DCHECK(tasks_after_boot_.empty());
-    thread_pool_->AddTask(self, task);
-  }
+  AddPostBootTask(self, new JitDoneCompilingProfileTask(dex_files));
   return added_to_queue;
 }
 
@@ -1678,6 +1677,15 @@
           : options_->GetThreadPoolPthreadPriority());
 }
 
+void Jit::AddPostBootTask(Thread* self, Task* task) {
+  MutexLock mu(self, boot_completed_lock_);
+  if (boot_completed_) {
+    thread_pool_->AddTask(self, task);
+  } else {
+    tasks_after_boot_.push_back(task);
+  }
+}
+
 void Jit::BootCompleted() {
   Thread* self = Thread::Current();
   std::deque<Task*> tasks;
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index fc7f071..2ddcd2d 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -384,6 +384,9 @@
   // Adjust state after forking.
   void PostZygoteFork();
 
+  // Add a task to the queue, ensuring it runs after boot is finished.
+  void AddPostBootTask(Thread* self, Task* task);
+
   // Called when system finishes booting.
   void BootCompleted();
 
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 356a4dd..fb861a4 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -134,6 +134,7 @@
   }
 
   void SetCompilationState(ZygoteCompilationState state) {
+    DCHECK_LT(static_cast<uint8_t>(*compilation_state_), static_cast<uint8_t>(state));
     region_->WriteData(compilation_state_, state);
   }