Refactor deoptimization support in debugger

This CL prepares breakpoint support for inlined methods where we'll have to
deoptimize everything.

We move deoptimization-related information to Dbg class only (deoptimization
request queue, full deoptimization event count and deoptimization lock). We
replace MethodInstrumentionRequest by DeoptimizationRequest. This is used to
know which kind of deoptimization is required for a particular event.

It also simplifies lock ordering a bit during event setup: we no longer need to
hold the deoptimization lock while holding the breakpoint lock. Moreover, the
deoptimization lock should be held only after the event list lock.

Bug: 12187616
Change-Id: Iff13f004adaeb25e5d609238bacce0b9720510e6
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index 4c17c96..66ebb96 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -335,12 +335,10 @@
   AtomicInteger event_serial_;
 
   // Linked list of events requested by the debugger (breakpoints, class prep, etc).
-  Mutex event_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  Mutex event_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_BEFORE(Locks::breakpoint_lock_);
 
   JdwpEvent* event_list_ GUARDED_BY(event_list_lock_);
   size_t event_list_size_ GUARDED_BY(event_list_lock_);  // Number of elements in event_list_.
-  size_t full_deoptimization_requests_ GUARDED_BY(event_list_lock_);  // Number of events requiring
-                                                                      // full deoptimization.
 
   // Used to synchronize suspension of the event thread (to avoid receiving "resume"
   // events before the thread has finished suspending itself).
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index 427350e..9b3ea2e 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -163,11 +163,12 @@
    * If one or more "break"-type mods are used, register them with
    * the interpreter.
    */
+  DeoptimizationRequest req;
   for (int i = 0; i < pEvent->modCount; i++) {
     const JdwpEventMod* pMod = &pEvent->mods[i];
     if (pMod->modKind == MK_LOCATION_ONLY) {
       /* should only be for Breakpoint, Step, and Exception */
-      Dbg::WatchLocation(&pMod->locationOnly.loc);
+      Dbg::WatchLocation(&pMod->locationOnly.loc, &req);
     } else if (pMod->modKind == MK_STEP) {
       /* should only be for EK_SINGLE_STEP; should only be one */
       JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
@@ -181,6 +182,11 @@
       dumpEvent(pEvent);  /* TODO - need for field watches */
     }
   }
+  if (NeedsFullDeoptimization(pEvent->eventKind)) {
+    CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
+    CHECK(req.method == nullptr);
+    req.kind = DeoptimizationRequest::kFullDeoptimization;
+  }
 
   {
     /*
@@ -193,19 +199,11 @@
     }
     event_list_ = pEvent;
     ++event_list_size_;
-
-    /**
-     * Do we need to enable full deoptimization ?
-     */
-    if (NeedsFullDeoptimization(pEvent->eventKind)) {
-      if (full_deoptimization_requests_ == 0) {
-        // This is the first event that needs full deoptimization: enable it.
-        Dbg::EnableFullDeoptimization();
-      }
-      ++full_deoptimization_requests_;
-    }
   }
 
+  // TODO we can do better job here since we should process only one request: the one we just
+  // created.
+  Dbg::RequestDeoptimization(req);
   Dbg::ManageDeoptimization();
 
   return ERR_NONE;
@@ -238,31 +236,28 @@
   /*
    * Unhook us from the interpreter, if necessary.
    */
+  DeoptimizationRequest req;
   for (int i = 0; i < pEvent->modCount; i++) {
     JdwpEventMod* pMod = &pEvent->mods[i];
     if (pMod->modKind == MK_LOCATION_ONLY) {
       /* should only be for Breakpoint, Step, and Exception */
-      Dbg::UnwatchLocation(&pMod->locationOnly.loc);
+      Dbg::UnwatchLocation(&pMod->locationOnly.loc, &req);
     }
     if (pMod->modKind == MK_STEP) {
       /* should only be for EK_SINGLE_STEP; should only be one */
       Dbg::UnconfigureStep(pMod->step.threadId);
     }
   }
+  if (NeedsFullDeoptimization(pEvent->eventKind)) {
+    CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
+    CHECK(req.method == nullptr);
+    req.kind = DeoptimizationRequest::kFullUndeoptimization;
+  }
 
   --event_list_size_;
   CHECK(event_list_size_ != 0 || event_list_ == NULL);
 
-  /**
-   * Can we disable full deoptimization ?
-   */
-  if (NeedsFullDeoptimization(pEvent->eventKind)) {
-    --full_deoptimization_requests_;
-    if (full_deoptimization_requests_ == 0) {
-      // We no longer need full deoptimization.
-      Dbg::DisableFullDeoptimization();
-    }
-  }
+  Dbg::RequestDeoptimization(req);
 }
 
 /*
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index 77c963f..5fc0228 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -215,7 +215,6 @@
       event_list_lock_("JDWP event list lock", kJdwpEventListLock),
       event_list_(NULL),
       event_list_size_(0),
-      full_deoptimization_requests_(0),
       event_thread_lock_("JDWP event thread lock"),
       event_thread_cond_("JDWP event thread condition variable", event_thread_lock_),
       event_thread_id_(0),