Combine JDWP location events

The runtime now sends location events BREAKPOINT, SINGLE_STEP, METHOD_ENTRY,
METHOD_EXIT and METHOD_EXIT_WITH_RETURN_VALUE in the same JDWP event packet
when they relate to the same location.

We update the Dbg::UpdateDebugger method to take initial event flags and
returned value. It allows to call this method from DebugInstrumentationListener
so we can treat method entry/exit events with breakpoint and single-step.

In the interpreter, we ensure we do not call Instrumentation::DexPcMovedEvent
when Instrumentation::MethodEnterEvent has just been called or when we're about
to call Instrumentation::MethodExitEvent. This prevents from sending duplicated
events.

I measured the average performance impact on some benchmarks with a Nexus 4
without a debugger attached:
* 1%-2% for the computed-goto-based interpreter (default interpreter)
* 5%-10% for the switch-based interpreter.
This is mostly due to the test of the boolean flag for the method entry event.

Bug: https://code.google.com/p/android/issues/detail?id=68427
Bug: 11874828
Change-Id: Ic4ff61375ff6b4ed5825adeac09f61f97b4be619
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 9c13973..97c216d 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -48,11 +48,20 @@
   } while (false)
 
 // Code to run before each dex instruction.
-#define PREAMBLE()
+#define PREAMBLE()                                                                              \
+  do {                                                                                          \
+    DCHECK(!inst->IsReturn());                                                                  \
+    if (UNLIKELY(notified_method_entry_event)) {                                                \
+      notified_method_entry_event = false;                                                      \
+    } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {                                \
+      instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),  \
+                                       shadow_frame.GetMethod(), dex_pc);                       \
+    }                                                                                           \
+  } while (false)
 
 template<bool do_access_check, bool transaction_active>
 JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
-                                ShadowFrame& shadow_frame, JValue result_register) {
+                         ShadowFrame& shadow_frame, JValue result_register) {
   bool do_assignability_check = do_access_check;
   if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
     LOG(FATAL) << "Invalid shadow frame for interpreter use";
@@ -61,11 +70,13 @@
   self->VerifyStack();
 
   uint32_t dex_pc = shadow_frame.GetDexPC();
+  bool notified_method_entry_event = false;
   const instrumentation::Instrumentation* const instrumentation = Runtime::Current()->GetInstrumentation();
   if (LIKELY(dex_pc == 0)) {  // We are entering the method as opposed to deoptimizing..
     if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
       instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
                                         shadow_frame.GetMethod(), 0);
+      notified_method_entry_event = true;
     }
   }
   const uint16_t* const insns = code_item->insns_;
@@ -74,10 +85,6 @@
   while (true) {
     dex_pc = inst->GetDexPc(insns);
     shadow_frame.SetDexPC(dex_pc);
-    if (UNLIKELY(instrumentation->HasDexPcListeners())) {
-      instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc);
-    }
     TraceExecution(shadow_frame, inst, dex_pc, mh);
     inst_data = inst->Fetch16(0);
     switch (inst->Opcode(inst_data)) {
@@ -163,7 +170,6 @@
         break;
       }
       case Instruction::RETURN_VOID: {
-        PREAMBLE();
         JValue result;
         if (do_access_check) {
           // If access checks are required then the dex-to-dex compiler and analysis of
@@ -182,7 +188,6 @@
         return result;
       }
       case Instruction::RETURN_VOID_BARRIER: {
-        PREAMBLE();
         QuasiAtomic::MembarStoreLoad();
         JValue result;
         if (UNLIKELY(self->TestAllFlags())) {
@@ -196,7 +201,6 @@
         return result;
       }
       case Instruction::RETURN: {
-        PREAMBLE();
         JValue result;
         result.SetJ(0);
         result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
@@ -211,7 +215,6 @@
         return result;
       }
       case Instruction::RETURN_WIDE: {
-        PREAMBLE();
         JValue result;
         result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
         if (UNLIKELY(self->TestAllFlags())) {
@@ -225,7 +228,6 @@
         return result;
       }
       case Instruction::RETURN_OBJECT: {
-        PREAMBLE();
         JValue result;
         if (UNLIKELY(self->TestAllFlags())) {
           CheckSuspend(self);