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_;
};