Prevent moving GC from running during redefinition.

This could cause a deadlock during deoptimization.

Test: ART_USE_READ_BARRIER=true ART_READ_BARRIER_TYPE=TABLELOOKUP mma -j40 test-art-host
Change-Id: I57e4f1a50709bf4a1817227913e61f3ef434d04a
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 57cc938..926819d 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -39,6 +39,7 @@
 #include "base/logging.h"
 #include "events-inl.h"
 #include "gc/allocation_listener.h"
+#include "gc/heap.h"
 #include "instrumentation.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
@@ -574,6 +575,13 @@
   }
   // Get the mirror class now that we aren't allocating anymore.
   art::Handle<art::mirror::Class> art_class(hs.NewHandle(GetMirrorClass()));
+  // Disable GC and wait for it to be done if we are a moving GC.  This is fine since we are done
+  // allocating so no deadlocks.
+  art::gc::Heap* heap = runtime_->GetHeap();
+  if (heap->IsGcConcurrentAndMoving()) {
+    // GC moving objects can cause deadlocks as we are deoptimizing the stack.
+    heap->IncrementDisableMovingGC(self_);
+  }
   // Enable assertion that this thread isn't interrupted during this installation.
   // After this we will need to do real cleanup in case of failure. Prior to this we could simply
   // return and would let everything get cleaned up or harmlessly leaked.
@@ -601,6 +609,9 @@
     runtime_->GetThreadList()->ResumeAll();
     // Get back shared mutator lock as expected for return.
     self_->TransitionFromSuspendedToRunnable();
+    if (heap->IsGcConcurrentAndMoving()) {
+      heap->DecrementDisableMovingGC(self_);
+    }
     return result_;
   }
   if (!UpdateClass(art_class.Get(), new_dex_cache.Get())) {
@@ -610,6 +621,9 @@
     runtime_->GetThreadList()->ResumeAll();
     // Get back shared mutator lock as expected for return.
     self_->TransitionFromSuspendedToRunnable();
+    if (heap->IsGcConcurrentAndMoving()) {
+      heap->DecrementDisableMovingGC(self_);
+    }
     return result_;
   }
   // Ensure that obsolete methods are deoptimized. This is needed since optimized methods may have
@@ -632,6 +646,9 @@
   // TODO Do the dex_file_ release at a more reasonable place. This works but it muddles who really
   // owns the DexFile.
   dex_file_.release();
+  if (heap->IsGcConcurrentAndMoving()) {
+    heap->DecrementDisableMovingGC(self_);
+  }
   return OK;
 }