Revert^4 "JIT JNI stubs."

The original CL,
    https://android-review.googlesource.com/513417 ,
has a bug fixed in the Revert^2,
    https://android-review.googlesource.com/550579 ,
and this Revert^4 adds two more fixes:
    - fix obsolete native method getting interpreter
      entrypoint in 980-redefine-object,
    - fix random JIT GC flakiness in 667-jit-jni-stub.

Test: testrunner.py --host --prebuild --no-relocate \
      --no-image --jit -t 980-redefine-object
Bug: 65574695
Bug: 69843562

This reverts commit 056d7756152bb3ced81dd57781be5028428ce2bd.

Change-Id: Ic778686168b90e29816fd526e23141dcbe5ea880
diff --git a/runtime/managed_stack.h b/runtime/managed_stack.h
index 4f1984d..07078ec 100644
--- a/runtime/managed_stack.h
+++ b/runtime/managed_stack.h
@@ -24,6 +24,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "base/bit_utils.h"
 
 namespace art {
 
@@ -42,7 +43,9 @@
 class PACKED(4) ManagedStack {
  public:
   ManagedStack()
-      : top_quick_frame_(nullptr), link_(nullptr), top_shadow_frame_(nullptr) {}
+      : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)),
+        link_(nullptr),
+        top_shadow_frame_(nullptr) {}
 
   void PushManagedStackFragment(ManagedStack* fragment) {
     // Copy this top fragment into given fragment.
@@ -63,17 +66,36 @@
     return link_;
   }
 
+  ArtMethod** GetTopQuickFrameKnownNotTagged() const {
+    return tagged_top_quick_frame_.GetSpKnownNotTagged();
+  }
+
   ArtMethod** GetTopQuickFrame() const {
-    return top_quick_frame_;
+    return tagged_top_quick_frame_.GetSp();
+  }
+
+  bool GetTopQuickFrameTag() const {
+    return tagged_top_quick_frame_.GetTag();
+  }
+
+  bool HasTopQuickFrame() const {
+    return tagged_top_quick_frame_.GetTaggedSp() != 0u;
   }
 
   void SetTopQuickFrame(ArtMethod** top) {
     DCHECK(top_shadow_frame_ == nullptr);
-    top_quick_frame_ = top;
+    DCHECK_ALIGNED(top, 4u);
+    tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top);
   }
 
-  static size_t TopQuickFrameOffset() {
-    return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_);
+  void SetTopQuickFrameTagged(ArtMethod** top) {
+    DCHECK(top_shadow_frame_ == nullptr);
+    DCHECK_ALIGNED(top, 4u);
+    tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateTagged(top);
+  }
+
+  static size_t TaggedTopQuickFrameOffset() {
+    return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_);
   }
 
   ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame);
@@ -83,8 +105,12 @@
     return top_shadow_frame_;
   }
 
+  bool HasTopShadowFrame() const {
+    return GetTopShadowFrame() != nullptr;
+  }
+
   void SetTopShadowFrame(ShadowFrame* top) {
-    DCHECK(top_quick_frame_ == nullptr);
+    DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u);
     top_shadow_frame_ = top;
   }
 
@@ -97,7 +123,47 @@
   bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
 
  private:
-  ArtMethod** top_quick_frame_;
+  // Encodes the top quick frame (which must be at least 4-byte aligned)
+  // and a flag that marks the GenericJNI trampoline.
+  class TaggedTopQuickFrame {
+   public:
+    static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) {
+      DCHECK_ALIGNED(sp, 4u);
+      return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp));
+    }
+
+    static TaggedTopQuickFrame CreateTagged(ArtMethod** sp) {
+      DCHECK_ALIGNED(sp, 4u);
+      return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp) | 1u);
+    }
+
+    // Get SP known to be not tagged and non-null.
+    ArtMethod** GetSpKnownNotTagged() const {
+      DCHECK(!GetTag());
+      DCHECK_NE(tagged_sp_, 0u);
+      return reinterpret_cast<ArtMethod**>(tagged_sp_);
+    }
+
+    ArtMethod** GetSp() const {
+      return reinterpret_cast<ArtMethod**>(tagged_sp_ & ~static_cast<uintptr_t>(1u));
+    }
+
+    bool GetTag() const {
+      return (tagged_sp_ & 1u) != 0u;
+    }
+
+    uintptr_t GetTaggedSp() const {
+      return tagged_sp_;
+    }
+
+   private:
+    explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { }
+
+    uintptr_t tagged_sp_;
+  };
+  static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check");
+
+  TaggedTopQuickFrame tagged_top_quick_frame_;
   ManagedStack* link_;
   ShadowFrame* top_shadow_frame_;
 };