Fix relation between debuggable / JIT zygote.

- Move the logic to clear precompiled in ClassLinker.
- Add a null check on entries in ZygoteMap
- Avoid doing JIT zygote actions (precompile, remapping boot images)
when debuggable.

Test: android.jdwptunnel.cts.JdwpTunnelTest#testAttachDebuggerToProfileableApp
Bug: 144947842

(cherry-picked from commit c76232ef401a036a9828fd27f22163619d9c1944)

Merged-In: I9b5e391bb35aa04bbeba01b9b563b33f96395d2e
Change-Id: I9b5e391bb35aa04bbeba01b9b563b33f96395d2e
diff --git a/runtime/art_method.h b/runtime/art_method.h
index f769f52..70d8d15 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -214,6 +214,10 @@
   }
 
   bool IsPreCompiled() const {
+    if (IsIntrinsic()) {
+      // kAccCompileDontBother overlaps with kAccIntrinsicBits.
+      return false;
+    }
     uint32_t expected = (kAccPreCompiled | kAccCompileDontBother);
     return (GetAccessFlags() & expected) == expected;
   }
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 8ae57ff..474cc6d 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -980,6 +980,10 @@
 }
 
 void Jit::MapBootImageMethods() {
+  if (Runtime::Current()->IsJavaDebuggable()) {
+    LOG(INFO) << "Not mapping boot image methods due to process being debuggable";
+    return;
+  }
   CHECK_NE(fd_methods_.get(), -1);
   if (!code_cache_->GetZygoteMap()->CanMapBootImageMethods()) {
     LOG(WARNING) << "Not mapping boot image methods due to error from zygote";
@@ -1223,7 +1227,10 @@
     return;
   }
   Runtime* runtime = Runtime::Current();
-  if (runtime->IsSystemServer() && UseJitCompilation() && HasImageWithProfile()) {
+  // If the runtime is debuggable, no need to precompile methods.
+  if (runtime->IsSystemServer() &&
+      UseJitCompilation() && HasImageWithProfile() &&
+      !runtime->IsJavaDebuggable()) {
     thread_pool_->AddTask(Thread::Current(), new JitProfileTask(dex_files, class_loader));
   }
 }
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 7ad4700..8383002 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -884,37 +884,28 @@
 }
 
 void JitCodeCache::TransitionToDebuggable() {
-  // We want to discard JIT compiled methods that are non-debuggable. These are:
-  // - Methods compiled by the zygote (where the compiled code is in the zygote exec
-  //   space)
-  // - Methods that are precompiled in the method_code_map_.
-  //
-  // Also, we want to clear the precompiled flag to clear the effects of
-  // GetSavedEntryPointOfPreCompiledMethod.
+  // Check that none of our methods have an entrypoint in the zygote exec
+  // space (this should be taken care of by
+  // ClassLinker::UpdateEntryPointsClassVisitor.
   {
     MutexLock mu(Thread::Current(), *Locks::jit_lock_);
-    for (const auto& it : method_code_map_) {
-      ArtMethod* method = it.second;
-      if (IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode()) ||
-          method->IsPreCompiled()) {
-        method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
-      }
-      if (method->IsPreCompiled()) {
-        method->ClearPreCompiled();
+    if (kIsDebugBuild) {
+      for (const auto& it : method_code_map_) {
+        ArtMethod* method = it.second;
+        DCHECK(!method->IsPreCompiled());
+        DCHECK(!IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode()));
       }
     }
     // Not strictly necessary, but this map is useless now.
     saved_compiled_methods_map_.clear();
   }
-  for (const auto& entry : zygote_map_) {
-    ArtMethod* method = entry.method;
-    if (IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode())) {
-      method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
-    }
-    // We check if it's precompiled instead of DCHECKing it to support
-    // TransitionToDebuggable being called multiple times.
-    if (method->IsPreCompiled()) {
-      method->ClearPreCompiled();
+  if (kIsDebugBuild) {
+    for (const auto& entry : zygote_map_) {
+      ArtMethod* method = entry.method;
+      if (method != nullptr) {
+        DCHECK(!method->IsPreCompiled());
+        DCHECK(!IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode()));
+      }
     }
   }
 }
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index d8216d2..f13e05c 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -400,6 +400,11 @@
     return region->IsValid() && !IsSharedRegion(*region);
   }
 
+  // Return whether the given `ptr` is in the zygote executable memory space.
+  bool IsInZygoteExecSpace(const void* ptr) const {
+    return shared_region_.IsInExecSpace(ptr);
+  }
+
  private:
   JitCodeCache();
 
@@ -475,10 +480,6 @@
     return shared_region_.IsInDataSpace(ptr);
   }
 
-  bool IsInZygoteExecSpace(const void* ptr) const {
-    return shared_region_.IsInExecSpace(ptr);
-  }
-
   bool IsWeakAccessEnabled(Thread* self) const;
   void WaitUntilInlineCacheAccessible(Thread* self)
       REQUIRES(!Locks::jit_lock_)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1a83372..b62cd11 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -2829,6 +2829,20 @@
           !m.IsProxyMethod()) {
         instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
       }
+
+      if (Runtime::Current()->GetJit() != nullptr &&
+          Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code) &&
+          !m.IsNative()) {
+        DCHECK(!m.IsProxyMethod());
+        instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
+      }
+
+      if (m.IsPreCompiled()) {
+        // Precompilation is incompatible with debuggable, so clear the flag
+        // and update the entrypoint in case it has been compiled.
+        m.ClearPreCompiled();
+        instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
+      }
     }
     return true;
   }