Support unwinding though the switch interpreter.

Wrap the switch interpreter in small assembly method which defines
DEX PC in CFI and thus it allows libunwind to backtrace through it.

Bug: 22414682
Test: testrunner.py --host -t 137
Test: testrunner.py --target -t 137
Change-Id: I31dad9f0fb446151baaa99234b64f25c8ca2fa87
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index e35d80f..283885e 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -39,7 +39,8 @@
         /* Signal mterp to return to caller */                                                  \
         shadow_frame.SetDexPC(dex::kDexNoIndex);                                                \
       }                                                                                         \
-      return JValue(); /* Handled in caller. */                                                 \
+      ctx->result = JValue(); /* Handled in caller. */                                          \
+      return;                                                                                   \
     } else {                                                                                    \
       int32_t displacement =                                                                    \
           static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);         \
@@ -96,7 +97,8 @@
         /* OSR has completed execution of the method.  Signal mterp to return to caller */     \
         shadow_frame.SetDexPC(dex::kDexNoIndex);                                               \
       }                                                                                        \
-      return result;                                                                           \
+      ctx->result = result;                                                                    \
+      return;                                                                                  \
     }                                                                                          \
   } while (false)
 
@@ -193,13 +195,17 @@
 }
 
 template<bool do_access_check, bool transaction_active>
-JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& accessor,
-                         ShadowFrame& shadow_frame, JValue result_register,
-                         bool interpret_one_instruction) {
+void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
+  Thread* self = ctx->self;
+  const CodeItemDataAccessor& accessor = ctx->accessor;
+  ShadowFrame& shadow_frame = ctx->shadow_frame;
+  JValue result_register = ctx->result_register;
+  bool interpret_one_instruction = ctx->interpret_one_instruction;
   constexpr bool do_assignability_check = do_access_check;
   if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
     LOG(FATAL) << "Invalid shadow frame for interpreter use";
-    return JValue();
+    ctx->result = JValue();
+    return;
   }
   self->VerifyStack();
 
@@ -317,7 +323,8 @@
           /* Signal mterp to return to caller */
           shadow_frame.SetDexPC(dex::kDexNoIndex);
         }
-        return result;
+        ctx->result = result;
+        return;
       }
       case Instruction::RETURN_VOID: {
         PREAMBLE();
@@ -339,7 +346,8 @@
           /* Signal mterp to return to caller */
           shadow_frame.SetDexPC(dex::kDexNoIndex);
         }
-        return result;
+        ctx->result = result;
+        return;
       }
       case Instruction::RETURN: {
         PREAMBLE();
@@ -362,7 +370,8 @@
           /* Signal mterp to return to caller */
           shadow_frame.SetDexPC(dex::kDexNoIndex);
         }
-        return result;
+        ctx->result = result;
+        return;
       }
       case Instruction::RETURN_WIDE: {
         PREAMBLE();
@@ -384,7 +393,8 @@
           /* Signal mterp to return to caller */
           shadow_frame.SetDexPC(dex::kDexNoIndex);
         }
-        return result;
+        ctx->result = result;
+        return;
       }
       case Instruction::RETURN_OBJECT: {
         PREAMBLE();
@@ -428,7 +438,8 @@
           /* Signal mterp to return to caller */
           shadow_frame.SetDexPC(dex::kDexNoIndex);
         }
-        return result;
+        ctx->result = result;
+        return;
       }
       case Instruction::CONST_4: {
         PREAMBLE();
@@ -2487,26 +2498,19 @@
   } while (!interpret_one_instruction);
   // Record where we stopped.
   shadow_frame.SetDexPC(inst->GetDexPc(insns));
-  return result_register;
+  ctx->result = result_register;
+  return;
 }  // NOLINT(readability/fn_size)
 
-// Explicit definitions of ExecuteSwitchImpl.
+// Explicit definitions of ExecuteSwitchImplCpp.
 template HOT_ATTR
-JValue ExecuteSwitchImpl<true, false>(Thread* self, const CodeItemDataAccessor& accessor,
-                                      ShadowFrame& shadow_frame, JValue result_register,
-                                      bool interpret_one_instruction);
+void ExecuteSwitchImplCpp<true, false>(SwitchImplContext* ctx);
 template HOT_ATTR
-JValue ExecuteSwitchImpl<false, false>(Thread* self, const CodeItemDataAccessor& accessor,
-                                       ShadowFrame& shadow_frame, JValue result_register,
-                                       bool interpret_one_instruction);
+void ExecuteSwitchImplCpp<false, false>(SwitchImplContext* ctx);
 template
-JValue ExecuteSwitchImpl<true, true>(Thread* self, const CodeItemDataAccessor& accessor,
-                                     ShadowFrame& shadow_frame, JValue result_register,
-                                     bool interpret_one_instruction);
+void ExecuteSwitchImplCpp<true, true>(SwitchImplContext* ctx);
 template
-JValue ExecuteSwitchImpl<false, true>(Thread* self, const CodeItemDataAccessor& accessor,
-                                      ShadowFrame& shadow_frame, JValue result_register,
-                                      bool interpret_one_instruction);
+void ExecuteSwitchImplCpp<false, true>(SwitchImplContext* ctx);
 
 }  // namespace interpreter
 }  // namespace art