JDWP: fix breakpoint on catch statement

Setting a breakpoint on a catch statement in the source actually
installs the breakpoint on a DEX move-exception instruction. At this
point, an exception is pending in the current thread.

The issue is no exception must be pending in the current thread to
report the breakpoint event. This is required to be able to call JNI
functions to create JDWP ids.

This CL fixes it by clearing the pending exception before reporting
event and restore it after reporting the event.

Bug: 21382373

(cherry picked from commit de48aa6708a3d5dacf7db3d64965e23261fb15d3)

Change-Id: Ie107eb47b6f2559c4fa5297f4033e07baad06f38
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 0eb7f2b..ef1aa6a 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2806,7 +2806,27 @@
   JDWP::EventLocation location;
   SetEventLocation(&location, m, dex_pc);
 
+  // We need to be sure no exception is pending when calling JdwpState::PostLocationEvent.
+  // This is required to be able to call JNI functions to create JDWP ids. To achieve this,
+  // we temporarily clear the current thread's exception (if any) and will restore it after
+  // the call.
+  // Note: the only way to get a pending exception here is to suspend on a move-exception
+  // instruction.
+  Thread* const self = Thread::Current();
+  StackHandleScope<1> hs(self);
+  Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException()));
+  self->ClearException();
+  if (kIsDebugBuild && pending_exception.Get() != nullptr) {
+    const DexFile::CodeItem* code_item = location.method->GetCodeItem();
+    const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]);
+    CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode());
+  }
+
   gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value);
+
+  if (pending_exception.Get() != nullptr) {
+    self->SetException(pending_exception.Get());
+  }
 }
 
 void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc,