Fix exception handling during deoptimization

When interpreting a deoptimized shadow frame, we may start with a
pending exception thrown by a previous deoptimized shadow frame (from
a previous invoke). Therefore, we need to handle it before executing
any instruction, otherwise we execute incorrect code.

Because we need the DEX pc of the throwing instruction to find a
matching catch handler, we initialize deoptimized shadow frames with
the current DEX pc at the time the stack is deoptimized.
When we are about to interpret a deoptimized shadow frame, we need to
update the shadow frame with the DEX pc of the next instruction to
interpret. There are three cases:
- if there is no pending exception, this is the instruction following
the current one.
- if there is a pending exception and we found a matching catch
handler, this is the first instruction of this handler.
- if there is a pending exception but there is no matching catch
handler, we do not execute the deoptimized shadow frame and continue
to its caller.

The verifier now fails when a method starts with a move-exception
instruction. Indeed we cannot start executing a method with a pending
exception.

Bug: 19057915
Bug: 19041195
Bug: 18607595
Change-Id: I355ac81e6ac098edc7e3cc8c13dbfa24a2969ab2
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index b04a18b..9d988e9 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -493,7 +493,23 @@
   while (shadow_frame != NULL) {
     self->SetTopOfShadowStack(shadow_frame);
     const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
-    value = Execute(self, code_item, *shadow_frame, value);
+    const uint32_t dex_pc = shadow_frame->GetDexPC();
+    uint32_t new_dex_pc;
+    if (UNLIKELY(self->IsExceptionPending())) {
+      const instrumentation::Instrumentation* const instrumentation =
+          Runtime::Current()->GetInstrumentation();
+      uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc,
+                                                                    instrumentation);
+      new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
+                                  // or DexFile::kDexNoIndex if there is none.
+    } else {
+      const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
+      new_dex_pc = dex_pc + instr->SizeInCodeUnits();  // the dex pc of the next instruction.
+    }
+    if (new_dex_pc != DexFile::kDexNoIndex) {
+      shadow_frame->SetDexPC(new_dex_pc);
+      value = Execute(self, code_item, *shadow_frame, value);
+    }
     ShadowFrame* old_frame = shadow_frame;
     shadow_frame = shadow_frame->GetLink();
     delete old_frame;