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