1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_MANAGED_STACK_H_ 18 #define ART_RUNTIME_MANAGED_STACK_H_ 19 20 #include <cstdint> 21 #include <cstring> 22 #include <string> 23 24 #include <android-base/logging.h> 25 26 #include "base/locks.h" 27 #include "base/macros.h" 28 #include "base/bit_utils.h" 29 30 namespace art { 31 32 namespace mirror { 33 class Object; 34 } // namespace mirror 35 36 class ArtMethod; 37 class ShadowFrame; 38 template <typename T> class StackReference; 39 40 // The managed stack is used to record fragments of managed code stacks. Managed code stacks 41 // may either be shadow frames or lists of frames using fixed frame sizes. Transition records are 42 // necessary for transitions between code using different frame layouts and transitions into native 43 // code. 44 class PACKED(4) ManagedStack { 45 public: ManagedStack()46 ManagedStack() 47 : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)), 48 link_(nullptr), 49 top_shadow_frame_(nullptr) {} 50 PushManagedStackFragment(ManagedStack * fragment)51 void PushManagedStackFragment(ManagedStack* fragment) { 52 // Copy this top fragment into given fragment. 53 memcpy(fragment, this, sizeof(ManagedStack)); 54 // Clear this fragment, which has become the top. 55 memset(this, 0, sizeof(ManagedStack)); 56 // Link our top fragment onto the given fragment. 57 link_ = fragment; 58 } 59 PopManagedStackFragment(const ManagedStack & fragment)60 void PopManagedStackFragment(const ManagedStack& fragment) { 61 DCHECK(&fragment == link_); 62 // Copy this given fragment back to the top. 63 memcpy(this, &fragment, sizeof(ManagedStack)); 64 } 65 GetLink()66 ManagedStack* GetLink() const { 67 return link_; 68 } 69 GetTopQuickFrameKnownNotTagged()70 ArtMethod** GetTopQuickFrameKnownNotTagged() const { 71 return tagged_top_quick_frame_.GetSpKnownNotTagged(); 72 } 73 GetTopQuickFrame()74 ArtMethod** GetTopQuickFrame() const { 75 return tagged_top_quick_frame_.GetSp(); 76 } 77 GetTopQuickFrameTag()78 bool GetTopQuickFrameTag() const { 79 return tagged_top_quick_frame_.GetTag(); 80 } 81 HasTopQuickFrame()82 bool HasTopQuickFrame() const { 83 return tagged_top_quick_frame_.GetTaggedSp() != 0u; 84 } 85 SetTopQuickFrame(ArtMethod ** top)86 void SetTopQuickFrame(ArtMethod** top) { 87 DCHECK(top_shadow_frame_ == nullptr); 88 DCHECK_ALIGNED(top, 4u); 89 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top); 90 } 91 SetTopQuickFrameTagged(ArtMethod ** top)92 void SetTopQuickFrameTagged(ArtMethod** top) { 93 DCHECK(top_shadow_frame_ == nullptr); 94 DCHECK_ALIGNED(top, 4u); 95 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateTagged(top); 96 } 97 TaggedTopQuickFrameOffset()98 static constexpr size_t TaggedTopQuickFrameOffset() { 99 return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_); 100 } 101 102 ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame); 103 ALWAYS_INLINE ShadowFrame* PopShadowFrame(); 104 GetTopShadowFrame()105 ShadowFrame* GetTopShadowFrame() const { 106 return top_shadow_frame_; 107 } 108 HasTopShadowFrame()109 bool HasTopShadowFrame() const { 110 return GetTopShadowFrame() != nullptr; 111 } 112 SetTopShadowFrame(ShadowFrame * top)113 void SetTopShadowFrame(ShadowFrame* top) { 114 DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u); 115 top_shadow_frame_ = top; 116 } 117 TopShadowFrameOffset()118 static size_t TopShadowFrameOffset() { 119 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); 120 } 121 122 size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_); 123 124 bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; 125 126 private: 127 // Encodes the top quick frame (which must be at least 4-byte aligned) 128 // and a flag that marks the GenericJNI trampoline. 129 class TaggedTopQuickFrame { 130 public: CreateNotTagged(ArtMethod ** sp)131 static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) { 132 DCHECK_ALIGNED(sp, 4u); 133 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp)); 134 } 135 CreateTagged(ArtMethod ** sp)136 static TaggedTopQuickFrame CreateTagged(ArtMethod** sp) { 137 DCHECK_ALIGNED(sp, 4u); 138 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp) | 1u); 139 } 140 141 // Get SP known to be not tagged and non-null. GetSpKnownNotTagged()142 ArtMethod** GetSpKnownNotTagged() const { 143 DCHECK(!GetTag()); 144 DCHECK_NE(tagged_sp_, 0u); 145 return reinterpret_cast<ArtMethod**>(tagged_sp_); 146 } 147 GetSp()148 ArtMethod** GetSp() const { 149 return reinterpret_cast<ArtMethod**>(tagged_sp_ & ~static_cast<uintptr_t>(1u)); 150 } 151 GetTag()152 bool GetTag() const { 153 return (tagged_sp_ & 1u) != 0u; 154 } 155 GetTaggedSp()156 uintptr_t GetTaggedSp() const { 157 return tagged_sp_; 158 } 159 160 private: TaggedTopQuickFrame(uintptr_t tagged_sp)161 explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { } 162 163 uintptr_t tagged_sp_; 164 }; 165 static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check"); 166 167 TaggedTopQuickFrame tagged_top_quick_frame_; 168 ManagedStack* link_; 169 ShadowFrame* top_shadow_frame_; 170 }; 171 172 } // namespace art 173 174 #endif // ART_RUNTIME_MANAGED_STACK_H_ 175