Basic obsolete methods support

Add support for executing obsolete methods following redefinitions.
This support includes methods that have been jitted. This does not add
any additional validity checks to our redefinition functions.

Note using work-arounds to ensure 916 works pending some fixes to the
compiler, deoptimizer, or both.

Test: ./test/run-test --host 914
Test: ./test/run-test --host 915
Test: ./test/run-test --host 916
Test: mma -j40 test-art-host
Test: ART_TEST_JIT=true \
      ART_TEST_INTERPRETER=true mma -j40 test-art-host
Test: ./art/tools/run-jdwp-tests.sh --mode=host --variant=X64
Test: ./art/tools/run-jdwp-tests.sh --mode=host --variant=X64 --no-jit

Bug: 32369913
Bug: 33630159

Change-Id: I78ef95f484146f1fb93c37fc50f56575bdab2432
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 93f50ad..38c4728 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -624,6 +624,38 @@
   return CodeCacheSizeLocked();
 }
 
+// This invalidates old_method. Once this function returns one can no longer use old_method to
+// execute code unless it is fixed up. This fixup will happen later in the process of installing a
+// class redefinition.
+// TODO We should add some info to ArtMethod to note that 'old_method' has been invalidated and
+// shouldn't be used since it is no longer logically in the jit code cache.
+// TODO We should add DCHECKS that validate that the JIT is paused when this method is entered.
+void JitCodeCache::MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method) {
+  MutexLock mu(Thread::Current(), lock_);
+  // Update ProfilingInfo to the new one.
+  if (old_method->GetProfilingInfo(kRuntimePointerSize) != nullptr) {
+    DCHECK_EQ(old_method->GetProfilingInfo(kRuntimePointerSize)->GetMethod(), old_method);
+    ProfilingInfo* info = old_method->GetProfilingInfo(kRuntimePointerSize);
+    // Since the JIT should be paused and all threads suspended by the time this is called these
+    // checks should always pass.
+    DCHECK(!info->IsInUseByCompiler());
+    new_method->SetProfilingInfo(info);
+    info->method_ = new_method;
+  }
+  // Update method_code_map_ to point to the new method.
+  for (auto& it : method_code_map_) {
+    if (it.second == old_method) {
+      it.second = new_method;
+    }
+  }
+  // Update osr_code_map_ to point to the new method.
+  auto code_map = osr_code_map_.find(old_method);
+  if (code_map != osr_code_map_.end()) {
+    osr_code_map_.Put(new_method, code_map->second);
+    osr_code_map_.erase(old_method);
+  }
+}
+
 size_t JitCodeCache::CodeCacheSizeLocked() {
   return used_memory_for_code_;
 }
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 30e2efb..5bfe661 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -217,6 +217,11 @@
   void DisallowInlineCacheAccess() REQUIRES(!lock_);
   void BroadcastForInlineCacheAccess() REQUIRES(!lock_);
 
+  // Notify the code cache that the method at the pointer 'old_method' is being moved to the pointer
+  // 'new_method' since it is being made obsolete.
+  void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method)
+      REQUIRES(!lock_) REQUIRES(Locks::mutator_lock_);
+
  private:
   // Take ownership of maps.
   JitCodeCache(MemMap* code_map,
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index 9902bb5..9fbf2e3 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -128,7 +128,9 @@
   const uint32_t number_of_inline_caches_;
 
   // Method this profiling info is for.
-  ArtMethod* const method_;
+  // Not 'const' as JVMTI introduces obsolete methods that we implement by creating new ArtMethods.
+  // See JitCodeCache::MoveObsoleteMethod.
+  ArtMethod* method_;
 
   // Whether the ArtMethod is currently being compiled. This flag
   // is implicitly guarded by the JIT code cache lock.