Remove requirement of a ProfilingInfo for jitted code.

When pre-jitting (zygote or system server in jit zygote mode),
the profiling info is just memory overhead. Remove the need to have
one.

Bug: 119800099
Test: boot, testrunner.py --jit
Change-Id: Ie74d870eebef72c903225542e9b41dfe98132419
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 205077f..9ef5ec3 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -604,9 +604,8 @@
   switch (inline_cache_type) {
     case kInlineCacheNoData: {
       LOG_FAIL_NO_STAT()
-          << "Interface or virtual call to "
-          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
-          << " could not be statically determined";
+          << "No inline cache information for call to "
+          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex());
       return false;
     }
 
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index b828aaf..68bdf53 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -246,7 +246,7 @@
   return true;
 }
 
-bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr) {
+bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit) {
   DCHECK(Runtime::Current()->UseJitCompilation());
   DCHECK(!method->IsRuntimeMethod());
 
@@ -269,7 +269,7 @@
   // If we get a request to compile a proxy method, we pass the actual Java method
   // of that proxy method, as the compiler does not expect a proxy method.
   ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
-  if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) {
+  if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr, prejit)) {
     return false;
   }
 
@@ -561,6 +561,7 @@
     kCompile,
     kCompileBaseline,
     kCompileOsr,
+    kPreCompile,
   };
 
   JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) {
@@ -583,6 +584,7 @@
   void Run(Thread* self) override {
     ScopedObjectAccess soa(self);
     switch (kind_) {
+      case TaskKind::kPreCompile:
       case TaskKind::kCompile:
       case TaskKind::kCompileBaseline:
       case TaskKind::kCompileOsr: {
@@ -590,7 +592,8 @@
             method_,
             self,
             /* baseline= */ (kind_ == TaskKind::kCompileBaseline),
-            /* osr= */ (kind_ == TaskKind::kCompileOsr));
+            /* osr= */ (kind_ == TaskKind::kCompileOsr),
+            /* prejit= */ (kind_ == TaskKind::kPreCompile));
         break;
       }
       case TaskKind::kAllocateProfile: {
@@ -796,19 +799,15 @@
       if (class_linker->IsQuickToInterpreterBridge(entry_point) ||
           class_linker->IsQuickGenericJniStub(entry_point) ||
           class_linker->IsQuickResolutionStub(entry_point)) {
-        if (!method->IsNative()) {
-          // The compiler requires a ProfilingInfo object for non-native methods.
-          ProfilingInfo::Create(self, method, /* retry_allocation= */ true);
-        }
         // Special case ZygoteServer class so that it gets compiled before the
         // zygote enters it. This avoids needing to do OSR during app startup.
         // TODO: have a profile instead.
         if (!add_to_queue || method->GetDeclaringClass()->DescriptorEquals(
                 "Lcom/android/internal/os/ZygoteServer;")) {
-          CompileMethod(method, self, /* baseline= */ false, /* osr= */ false);
+          CompileMethod(method, self, /* baseline= */ false, /* osr= */ false, /* prejit= */ true);
         } else {
           thread_pool_->AddTask(self,
-              new JitCompileTask(method, JitCompileTask::TaskKind::kCompile));
+              new JitCompileTask(method, JitCompileTask::TaskKind::kPreCompile));
         }
       }
     }
@@ -890,7 +889,7 @@
         method->IsNative() &&
         Runtime::Current()->IsUsingApexBootImageLocation()) {
       // jitzygote: Compile JNI stub on first use to avoid the expensive generic stub.
-      CompileMethod(method, self, /* baseline= */ false, /* osr= */ false);
+      CompileMethod(method, self, /* baseline= */ false, /* osr= */ false, /* prejit= */ false);
       return true;
     }
     if (old_count < HotMethodThreshold() && new_count >= HotMethodThreshold()) {
@@ -935,11 +934,7 @@
   if (UNLIKELY(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse())) {
     ArtMethod* np_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
     if (np_method->IsCompilable()) {
-      if (!np_method->IsNative()) {
-        // The compiler requires a ProfilingInfo object for non-native methods.
-        ProfilingInfo::Create(thread, np_method, /* retry_allocation= */ true);
-      }
-      JitCompileTask compile_task(method, JitCompileTask::TaskKind::kCompile);
+      JitCompileTask compile_task(method, JitCompileTask::TaskKind::kPreCompile);
       // Fake being in a runtime thread so that class-load behavior will be the same as normal jit.
       ScopedSetRuntimeThread ssrt(thread);
       compile_task.Run(thread);
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 4b81f71..92d2b55 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -170,7 +170,7 @@
   // Create JIT itself.
   static Jit* Create(JitCodeCache* code_cache, JitOptions* options);
 
-  bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr)
+  bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   const JitCodeCache* GetCodeCache() const {
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 65e6d9d..2505111 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -1127,12 +1127,15 @@
         // This situation currently only occurs in the jit-zygote mode.
         DCHECK(Runtime::Current()->IsZygote());
         DCHECK(Runtime::Current()->IsUsingApexBootImageLocation());
-        DCHECK(method->GetProfilingInfo(kRuntimePointerSize) != nullptr);
         DCHECK(method->GetDeclaringClass()->GetClassLoader() == nullptr);
-        // Save the entrypoint, so it can be fethed later once the class is
-        // initialized.
-        method->GetProfilingInfo(kRuntimePointerSize)->SetSavedEntryPoint(
-            method_header->GetEntryPoint());
+        // TODO(ngeoffray): In most cases, the zygote will not have a profiling
+        // info for a compiled method. Use a map instead.
+        if (method->GetProfilingInfo(kRuntimePointerSize) != nullptr) {
+          // Save the entrypoint, so it can be fetched later once the class is
+          // initialized.
+          method->GetProfilingInfo(kRuntimePointerSize)->SetSavedEntryPoint(
+              method_header->GetEntryPoint());
+        }
       } else {
         Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
             method, method_header->GetEntryPoint());
@@ -1564,8 +1567,6 @@
           }
         }
 
-        DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
-
         // Change entry points of native methods back to the GenericJNI entrypoint.
         for (const auto& entry : jni_stubs_map_) {
           const JniStubData& data = entry.second;
@@ -1743,30 +1744,9 @@
         return false;
       });
     profiling_infos_.erase(profiling_kept_end, profiling_infos_.end());
-    DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
   }
 }
 
-bool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() {
-  ScopedTrace trace(__FUNCTION__);
-  // Check that methods we have compiled do have a ProfilingInfo object. We would
-  // have memory leaks of compiled code otherwise.
-  for (const auto& it : method_code_map_) {
-    ArtMethod* method = it.second;
-    if (method->GetProfilingInfo(kRuntimePointerSize) == nullptr) {
-      const void* code_ptr = it.first;
-      const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
-      if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
-        // If the code is not dead, then we have a problem. Note that this can even
-        // happen just after a collection, as mutator threads are running in parallel
-        // and could deoptimize an existing compiled code.
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
 OatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) {
   static_assert(kRuntimeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
   if (kRuntimeISA == InstructionSet::kArm) {
@@ -2003,16 +1983,16 @@
   return osr_code_map_.find(method) != osr_code_map_.end();
 }
 
-bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) {
+bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr, bool prejit) {
   if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
     return false;
   }
 
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   if (class_linker->IsQuickResolutionStub(method->GetEntryPointFromQuickCompiledCode())) {
-    if (!Runtime::Current()->IsUsingApexBootImageLocation() || !Runtime::Current()->IsZygote()) {
-      // Unless we're running as zygote in the jitzygote experiment, we currently don't save
-      // the JIT compiled code if we cannot update the entrypoint due to having the resolution stub.
+    if (!prejit) {
+      // Unless we're pre-jitting, we currently don't save the JIT compiled code if we cannot
+      // update the entrypoint due to having the resolution stub.
       VLOG(jit) << "Not compiling "
                 << method->PrettyMethod()
                 << " because it has the resolution stub";
@@ -2064,18 +2044,20 @@
   } else {
     ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
     if (info == nullptr) {
-      VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled";
-      // Because the counter is not atomic, there are some rare cases where we may not hit the
-      // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this.
-      ClearMethodCounter(method, /*was_warm=*/ false);
-      return false;
+      // When prejitting, we don't allocate a profiling info.
+      if (!prejit) {
+        VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled";
+        // Because the counter is not atomic, there are some rare cases where we may not hit the
+        // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this.
+        ClearMethodCounter(method, /*was_warm=*/ false);
+        return false;
+      }
+    } else {
+      if (info->IsMethodBeingCompiled(osr)) {
+        return false;
+      }
+      info->SetIsMethodBeingCompiled(true, osr);
     }
-
-    if (info->IsMethodBeingCompiled(osr)) {
-      return false;
-    }
-
-    info->SetIsMethodBeingCompiled(true, osr);
     return true;
   }
 }
@@ -2113,8 +2095,10 @@
     }  // else CommitCodeInternal() updated entrypoints of all methods in the JniStubData.
   } else {
     ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-    DCHECK(info->IsMethodBeingCompiled(osr));
-    info->SetIsMethodBeingCompiled(false, osr);
+    if (info != nullptr) {
+      DCHECK(info->IsMethodBeingCompiled(osr));
+      info->SetIsMethodBeingCompiled(false, osr);
+    }
   }
 }
 
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index a3e10c7..3078e2b 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -101,7 +101,7 @@
                               std::string* error_msg);
   ~JitCodeCache();
 
-  bool NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr)
+  bool NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr, bool prejit)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!lock_);
 
@@ -381,10 +381,6 @@
       REQUIRES(!lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool CheckLiveCompiledCodeHasProfilingInfo()
-      REQUIRES(lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   CodeCacheBitmap* GetLiveBitmap() const {
     return live_bitmap_.get();
   }
diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc
index 00827cf..15187f3 100644
--- a/test/566-polymorphic-inlining/polymorphic_inline.cc
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -46,7 +46,7 @@
       usleep(1000);
     }
     // Will either ensure it's compiled or do the compilation itself.
-    jit->CompileMethod(method, soa.Self(), /*baseline=*/ false, /*osr=*/ false);
+    jit->CompileMethod(method, soa.Self(), /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false);
   }
 
   CodeInfo info(header);
diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc
index dc0e94c..ee978c2 100644
--- a/test/570-checker-osr/osr.cc
+++ b/test/570-checker-osr/osr.cc
@@ -128,7 +128,8 @@
           // Sleep to yield to the compiler thread.
           usleep(1000);
           // Will either ensure it's compiled or do the compilation itself.
-          jit->CompileMethod(m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true);
+          jit->CompileMethod(
+              m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true, /*prejit=*/ false);
         }
       });
 }
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index a0b2f1e..7b023de 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -246,7 +246,7 @@
         ProfilingInfo::Create(self, method, /* retry_allocation */ true);
       }
       // Will either ensure it's compiled or do the compilation itself.
-      jit->CompileMethod(method, self, /*baseline=*/ false, /*osr=*/ false);
+      jit->CompileMethod(method, self, /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false);
     }
   }
 }