Fix the stack at the beginning of the Generic JNI trampoline.

Fix up a callee-save frame at the bottom of the stack while we
check for optimization annotations, thus allowing stack walking
until the completion of the JNI frame creation.

Test: art/test/testrunner/testrunner.py -t 656-annotation-lookup-generic-jni
Bug: 38454151
Bug: 34659969
Change-Id: I70dc3d40139198f29457dba5282b45a9d0d09e49
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index b7cd39f..4e54045 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2181,11 +2181,34 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ArtMethod* called = *sp;
   DCHECK(called->IsNative()) << called->PrettyMethod(true);
+  // Fix up a callee-save frame at the bottom of the stack (at `*sp`,
+  // above the alloca region) while we check for optimization
+  // annotations, thus allowing stack walking until the completion of
+  // the JNI frame creation.
+  //
+  // Note however that the Generic JNI trampoline does not expect
+  // exception being thrown at that stage.
+  *sp = Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs);
+  self->SetTopOfStack(sp);
   uint32_t shorty_len = 0;
   const char* shorty = called->GetShorty(&shorty_len);
   bool critical_native = called->IsAnnotatedWithCriticalNative();
+  // ArtMethod::IsAnnotatedWithCriticalNative should not throw
+  // an exception; clear it if it happened anyway.
+  // TODO: Revisit this code path and turn this into a CHECK(!self->IsExceptionPending()).
+  if (self->IsExceptionPending()) {
+    self->ClearException();
+  }
   bool fast_native = called->IsAnnotatedWithFastNative();
+  // ArtMethod::IsAnnotatedWithFastNative should not throw
+  // an exception; clear it if it happened anyway.
+  // TODO: Revisit this code path and turn this into a CHECK(!self->IsExceptionPending()).
+  if (self->IsExceptionPending()) {
+    self->ClearException();
+  }
   bool normal_native = !critical_native && !fast_native;
+  // Restore the initial ArtMethod pointer at `*sp`.
+  *sp = called;
 
   // Run the visitor and update sp.
   BuildGenericJniFrameVisitor visitor(self,