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: 46 static size_t constexpr kTaggedJniSpMask = 0x3; 47 ManagedStack()48 ManagedStack() 49 : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)), 50 link_(nullptr), 51 top_shadow_frame_(nullptr) {} 52 PushManagedStackFragment(ManagedStack * fragment)53 void PushManagedStackFragment(ManagedStack* fragment) { 54 // Copy this top fragment into given fragment. 55 memcpy(fragment, this, sizeof(ManagedStack)); 56 // Clear this fragment, which has become the top. 57 memset(this, 0, sizeof(ManagedStack)); 58 // Link our top fragment onto the given fragment. 59 link_ = fragment; 60 } 61 PopManagedStackFragment(const ManagedStack & fragment)62 void PopManagedStackFragment(const ManagedStack& fragment) { 63 DCHECK(&fragment == link_); 64 // Copy this given fragment back to the top. 65 memcpy(this, &fragment, sizeof(ManagedStack)); 66 } 67 GetLink()68 ManagedStack* GetLink() const { 69 return link_; 70 } 71 GetTopQuickFrameKnownNotTagged()72 ArtMethod** GetTopQuickFrameKnownNotTagged() const { 73 return tagged_top_quick_frame_.GetSpKnownNotTagged(); 74 } 75 GetTopQuickFrame()76 ArtMethod** GetTopQuickFrame() const { 77 return tagged_top_quick_frame_.GetSp(); 78 } 79 GetTopQuickFrameGenericJniTag()80 bool GetTopQuickFrameGenericJniTag() const { 81 return tagged_top_quick_frame_.GetGenericJniTag(); 82 } 83 GetTopQuickFrameJitJniTag()84 bool GetTopQuickFrameJitJniTag() const { 85 return tagged_top_quick_frame_.GetJitJniTag(); 86 } 87 HasTopQuickFrame()88 bool HasTopQuickFrame() const { 89 return tagged_top_quick_frame_.GetTaggedSp() != 0u; 90 } 91 SetTopQuickFrame(ArtMethod ** top)92 void SetTopQuickFrame(ArtMethod** top) { 93 DCHECK(top_shadow_frame_ == nullptr); 94 DCHECK_ALIGNED(top, 4u); 95 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top); 96 } 97 SetTopQuickFrameGenericJniTagged(ArtMethod ** top)98 void SetTopQuickFrameGenericJniTagged(ArtMethod** top) { 99 DCHECK(top_shadow_frame_ == nullptr); 100 DCHECK_ALIGNED(top, 4u); 101 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateGenericJniTagged(top); 102 } 103 TaggedTopQuickFrameOffset()104 static constexpr size_t TaggedTopQuickFrameOffset() { 105 return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_); 106 } 107 108 ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame); 109 ALWAYS_INLINE ShadowFrame* PopShadowFrame(); 110 GetTopShadowFrame()111 ShadowFrame* GetTopShadowFrame() const { 112 return top_shadow_frame_; 113 } 114 HasTopShadowFrame()115 bool HasTopShadowFrame() const { 116 return GetTopShadowFrame() != nullptr; 117 } 118 SetTopShadowFrame(ShadowFrame * top)119 void SetTopShadowFrame(ShadowFrame* top) { 120 DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u); 121 top_shadow_frame_ = top; 122 } 123 TopShadowFrameOffset()124 static size_t TopShadowFrameOffset() { 125 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); 126 } 127 128 private: 129 // Encodes the top quick frame (which must be at least 4-byte aligned) 130 // and a flag that marks the GenericJNI trampoline. 131 class TaggedTopQuickFrame { 132 public: CreateNotTagged(ArtMethod ** sp)133 static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) { 134 DCHECK_ALIGNED(sp, 4u); 135 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp)); 136 } 137 CreateGenericJniTagged(ArtMethod ** sp)138 static TaggedTopQuickFrame CreateGenericJniTagged(ArtMethod** sp) { 139 DCHECK_ALIGNED(sp, 4u); 140 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp) | 1u); 141 } 142 143 // Get SP known to be not tagged and non-null. GetSpKnownNotTagged()144 ArtMethod** GetSpKnownNotTagged() const { 145 DCHECK(!GetGenericJniTag() && !GetJitJniTag()); 146 DCHECK_NE(tagged_sp_, 0u); 147 return reinterpret_cast<ArtMethod**>(tagged_sp_); 148 } 149 GetSp()150 ArtMethod** GetSp() const { 151 return reinterpret_cast<ArtMethod**>(tagged_sp_ & ~static_cast<uintptr_t>(kTaggedJniSpMask)); 152 } 153 GetGenericJniTag()154 bool GetGenericJniTag() const { 155 return (tagged_sp_ & 1u) != 0u; 156 } 157 GetJitJniTag()158 bool GetJitJniTag() const { 159 return (tagged_sp_ & 2u) != 0u; 160 } 161 GetTaggedSp()162 uintptr_t GetTaggedSp() const { 163 return tagged_sp_; 164 } 165 166 private: TaggedTopQuickFrame(uintptr_t tagged_sp)167 explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { } 168 169 uintptr_t tagged_sp_; 170 }; 171 static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check"); 172 173 TaggedTopQuickFrame tagged_top_quick_frame_; 174 ManagedStack* link_; 175 ShadowFrame* top_shadow_frame_; 176 }; 177 178 } // namespace art 179 180 #endif // ART_RUNTIME_MANAGED_STACK_H_ 181