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_STACK_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_STACK_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <stdint.h> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include <optional> 23*795d594fSAndroid Build Coastguard Worker #include <string> 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker #include "base/locks.h" 26*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 27*795d594fSAndroid Build Coastguard Worker #include "deoptimization_kind.h" 28*795d594fSAndroid Build Coastguard Worker #include "oat/stack_map.h" 29*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h" 30*795d594fSAndroid Build Coastguard Worker #include "quick/quick_method_frame_info.h" 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker namespace mirror { 35*795d594fSAndroid Build Coastguard Worker class Object; 36*795d594fSAndroid Build Coastguard Worker } // namespace mirror 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker class ArtMethod; 39*795d594fSAndroid Build Coastguard Worker class Context; 40*795d594fSAndroid Build Coastguard Worker class HandleScope; 41*795d594fSAndroid Build Coastguard Worker class OatQuickMethodHeader; 42*795d594fSAndroid Build Coastguard Worker class ShadowFrame; 43*795d594fSAndroid Build Coastguard Worker class Thread; 44*795d594fSAndroid Build Coastguard Worker union JValue; 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker // The kind of vreg being accessed in calls to Set/GetVReg. 47*795d594fSAndroid Build Coastguard Worker enum VRegKind { 48*795d594fSAndroid Build Coastguard Worker kReferenceVReg, 49*795d594fSAndroid Build Coastguard Worker kIntVReg, 50*795d594fSAndroid Build Coastguard Worker kFloatVReg, 51*795d594fSAndroid Build Coastguard Worker kLongLoVReg, 52*795d594fSAndroid Build Coastguard Worker kLongHiVReg, 53*795d594fSAndroid Build Coastguard Worker kDoubleLoVReg, 54*795d594fSAndroid Build Coastguard Worker kDoubleHiVReg, 55*795d594fSAndroid Build Coastguard Worker kConstant, 56*795d594fSAndroid Build Coastguard Worker kImpreciseConstant, 57*795d594fSAndroid Build Coastguard Worker kUndefined, 58*795d594fSAndroid Build Coastguard Worker }; 59*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, VRegKind rhs); 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker /* 62*795d594fSAndroid Build Coastguard Worker * Our current stack layout. 63*795d594fSAndroid Build Coastguard Worker * The Dalvik registers come first, followed by the 64*795d594fSAndroid Build Coastguard Worker * Method*, followed by other special temporaries if any, followed by 65*795d594fSAndroid Build Coastguard Worker * regular compiler temporary. As of now we only have the Method* as 66*795d594fSAndroid Build Coastguard Worker * as a special compiler temporary. 67*795d594fSAndroid Build Coastguard Worker * A compiler temporary can be thought of as a virtual register that 68*795d594fSAndroid Build Coastguard Worker * does not exist in the dex but holds intermediate values to help 69*795d594fSAndroid Build Coastguard Worker * optimizations and code generation. A special compiler temporary is 70*795d594fSAndroid Build Coastguard Worker * one whose location in frame is well known while non-special ones 71*795d594fSAndroid Build Coastguard Worker * do not have a requirement on location in frame as long as code 72*795d594fSAndroid Build Coastguard Worker * generator itself knows how to access them. 73*795d594fSAndroid Build Coastguard Worker * 74*795d594fSAndroid Build Coastguard Worker * TODO: Update this documentation? 75*795d594fSAndroid Build Coastguard Worker * 76*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 77*795d594fSAndroid Build Coastguard Worker * | IN[ins-1] | {Note: resides in caller's frame} 78*795d594fSAndroid Build Coastguard Worker * | . | 79*795d594fSAndroid Build Coastguard Worker * | IN[0] | 80*795d594fSAndroid Build Coastguard Worker * | caller's ArtMethod | ... ArtMethod* 81*795d594fSAndroid Build Coastguard Worker * +===============================+ {Note: start of callee's frame} 82*795d594fSAndroid Build Coastguard Worker * | core callee-save spill | {variable sized} 83*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 84*795d594fSAndroid Build Coastguard Worker * | fp callee-save spill | 85*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 86*795d594fSAndroid Build Coastguard Worker * | filler word | {For compatibility, if V[locals-1] used as wide 87*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 88*795d594fSAndroid Build Coastguard Worker * | V[locals-1] | 89*795d594fSAndroid Build Coastguard Worker * | V[locals-2] | 90*795d594fSAndroid Build Coastguard Worker * | . | 91*795d594fSAndroid Build Coastguard Worker * | . | ... (reg == 2) 92*795d594fSAndroid Build Coastguard Worker * | V[1] | ... (reg == 1) 93*795d594fSAndroid Build Coastguard Worker * | V[0] | ... (reg == 0) <---- "locals_start" 94*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 95*795d594fSAndroid Build Coastguard Worker * | stack alignment padding | {0 to (kStackAlignWords-1) of padding} 96*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 97*795d594fSAndroid Build Coastguard Worker * | Compiler temp region | ... (reg >= max_num_special_temps) 98*795d594fSAndroid Build Coastguard Worker * | . | 99*795d594fSAndroid Build Coastguard Worker * | . | 100*795d594fSAndroid Build Coastguard Worker * | V[max_num_special_temps + 1] | 101*795d594fSAndroid Build Coastguard Worker * | V[max_num_special_temps + 0] | 102*795d594fSAndroid Build Coastguard Worker * +-------------------------------+ 103*795d594fSAndroid Build Coastguard Worker * | OUT[outs-1] | 104*795d594fSAndroid Build Coastguard Worker * | OUT[outs-2] | 105*795d594fSAndroid Build Coastguard Worker * | . | 106*795d594fSAndroid Build Coastguard Worker * | OUT[0] | 107*795d594fSAndroid Build Coastguard Worker * | ArtMethod* | ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned 108*795d594fSAndroid Build Coastguard Worker * +===============================+ 109*795d594fSAndroid Build Coastguard Worker */ 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker class StackVisitor { 112*795d594fSAndroid Build Coastguard Worker public: 113*795d594fSAndroid Build Coastguard Worker // This enum defines a flag to control whether inlined frames are included 114*795d594fSAndroid Build Coastguard Worker // when walking the stack. 115*795d594fSAndroid Build Coastguard Worker enum class StackWalkKind { 116*795d594fSAndroid Build Coastguard Worker kIncludeInlinedFrames, 117*795d594fSAndroid Build Coastguard Worker kSkipInlinedFrames, 118*795d594fSAndroid Build Coastguard Worker }; 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Worker protected: 121*795d594fSAndroid Build Coastguard Worker EXPORT StackVisitor(Thread* thread, 122*795d594fSAndroid Build Coastguard Worker Context* context, 123*795d594fSAndroid Build Coastguard Worker StackWalkKind walk_kind, 124*795d594fSAndroid Build Coastguard Worker bool check_suspended = true); 125*795d594fSAndroid Build Coastguard Worker 126*795d594fSAndroid Build Coastguard Worker bool GetRegisterIfAccessible(uint32_t reg, DexRegisterLocation::Kind kind, uint32_t* val) const 127*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 128*795d594fSAndroid Build Coastguard Worker 129*795d594fSAndroid Build Coastguard Worker public: ~StackVisitor()130*795d594fSAndroid Build Coastguard Worker virtual ~StackVisitor() {} 131*795d594fSAndroid Build Coastguard Worker StackVisitor(const StackVisitor&) = default; 132*795d594fSAndroid Build Coastguard Worker StackVisitor(StackVisitor&&) = default; 133*795d594fSAndroid Build Coastguard Worker 134*795d594fSAndroid Build Coastguard Worker // Return 'true' if we should continue to visit more frames, 'false' to stop. 135*795d594fSAndroid Build Coastguard Worker virtual bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) = 0; 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker enum class EXPORT CountTransitions { 138*795d594fSAndroid Build Coastguard Worker kYes, 139*795d594fSAndroid Build Coastguard Worker kNo, 140*795d594fSAndroid Build Coastguard Worker }; 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker template <CountTransitions kCount = CountTransitions::kYes> 143*795d594fSAndroid Build Coastguard Worker EXPORT void WalkStack(bool include_transitions = false) REQUIRES_SHARED(Locks::mutator_lock_); 144*795d594fSAndroid Build Coastguard Worker 145*795d594fSAndroid Build Coastguard Worker // Convenience helper function to walk the stack with a lambda as a visitor. 146*795d594fSAndroid Build Coastguard Worker template <CountTransitions kCountTransitions = CountTransitions::kYes, 147*795d594fSAndroid Build Coastguard Worker typename T> 148*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static void WalkStack(const T& fn, 149*795d594fSAndroid Build Coastguard Worker Thread* thread, 150*795d594fSAndroid Build Coastguard Worker Context* context, 151*795d594fSAndroid Build Coastguard Worker StackWalkKind walk_kind, 152*795d594fSAndroid Build Coastguard Worker bool check_suspended = true, 153*795d594fSAndroid Build Coastguard Worker bool include_transitions = false) REQUIRES_SHARED(Locks::mutator_lock_)154*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 155*795d594fSAndroid Build Coastguard Worker class LambdaStackVisitor : public StackVisitor { 156*795d594fSAndroid Build Coastguard Worker public: 157*795d594fSAndroid Build Coastguard Worker LambdaStackVisitor(const T& fn, 158*795d594fSAndroid Build Coastguard Worker Thread* thread, 159*795d594fSAndroid Build Coastguard Worker Context* context, 160*795d594fSAndroid Build Coastguard Worker StackWalkKind walk_kind, 161*795d594fSAndroid Build Coastguard Worker bool check_suspended = true) 162*795d594fSAndroid Build Coastguard Worker : StackVisitor(thread, context, walk_kind, check_suspended), fn_(fn) {} 163*795d594fSAndroid Build Coastguard Worker 164*795d594fSAndroid Build Coastguard Worker bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { 165*795d594fSAndroid Build Coastguard Worker return fn_(this); 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker private: 169*795d594fSAndroid Build Coastguard Worker T fn_; 170*795d594fSAndroid Build Coastguard Worker }; 171*795d594fSAndroid Build Coastguard Worker LambdaStackVisitor visitor(fn, thread, context, walk_kind, check_suspended); 172*795d594fSAndroid Build Coastguard Worker visitor.template WalkStack<kCountTransitions>(include_transitions); 173*795d594fSAndroid Build Coastguard Worker } 174*795d594fSAndroid Build Coastguard Worker GetThread()175*795d594fSAndroid Build Coastguard Worker Thread* GetThread() const { 176*795d594fSAndroid Build Coastguard Worker return thread_; 177*795d594fSAndroid Build Coastguard Worker } 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker EXPORT ArtMethod* GetMethod() const REQUIRES_SHARED(Locks::mutator_lock_); 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker // Sets this stack frame's method pointer. This requires a full lock of the MutatorLock. This 182*795d594fSAndroid Build Coastguard Worker // doesn't work with inlined methods. 183*795d594fSAndroid Build Coastguard Worker EXPORT void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_); 184*795d594fSAndroid Build Coastguard Worker GetOuterMethod()185*795d594fSAndroid Build Coastguard Worker ArtMethod* GetOuterMethod() const { 186*795d594fSAndroid Build Coastguard Worker return *GetCurrentQuickFrame(); 187*795d594fSAndroid Build Coastguard Worker } 188*795d594fSAndroid Build Coastguard Worker IsShadowFrame()189*795d594fSAndroid Build Coastguard Worker bool IsShadowFrame() const { 190*795d594fSAndroid Build Coastguard Worker return cur_shadow_frame_ != nullptr; 191*795d594fSAndroid Build Coastguard Worker } 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker EXPORT uint32_t GetDexPc(bool abort_on_failure = true) const 194*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 195*795d594fSAndroid Build Coastguard Worker 196*795d594fSAndroid Build Coastguard Worker // Returns a vector of the inlined dex pcs, in order from outermost to innermost but it replaces 197*795d594fSAndroid Build Coastguard Worker // the innermost one with `handler_dex_pc`. In essence, (outermost dex pc, mid dex pc #1, ..., mid 198*795d594fSAndroid Build Coastguard Worker // dex pc #n-1, `handler_dex_pc`). 199*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> ComputeDexPcList(uint32_t handler_dex_pc) const 200*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker EXPORT ObjPtr<mirror::Object> GetThisObject() const REQUIRES_SHARED(Locks::mutator_lock_); 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker EXPORT size_t GetNativePcOffset() const REQUIRES_SHARED(Locks::mutator_lock_); 205*795d594fSAndroid Build Coastguard Worker 206*795d594fSAndroid Build Coastguard Worker // Returns the height of the stack in the managed stack frames, including transitions. GetFrameHeight()207*795d594fSAndroid Build Coastguard Worker size_t GetFrameHeight() REQUIRES_SHARED(Locks::mutator_lock_) { 208*795d594fSAndroid Build Coastguard Worker return GetNumFrames() - cur_depth_ - 1; 209*795d594fSAndroid Build Coastguard Worker } 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker // Returns a frame ID for JDWP use, starting from 1. GetFrameId()212*795d594fSAndroid Build Coastguard Worker size_t GetFrameId() REQUIRES_SHARED(Locks::mutator_lock_) { 213*795d594fSAndroid Build Coastguard Worker return GetFrameHeight() + 1; 214*795d594fSAndroid Build Coastguard Worker } 215*795d594fSAndroid Build Coastguard Worker GetNumFrames()216*795d594fSAndroid Build Coastguard Worker size_t GetNumFrames() REQUIRES_SHARED(Locks::mutator_lock_) { 217*795d594fSAndroid Build Coastguard Worker if (num_frames_ == 0) { 218*795d594fSAndroid Build Coastguard Worker num_frames_ = ComputeNumFrames(thread_, walk_kind_); 219*795d594fSAndroid Build Coastguard Worker } 220*795d594fSAndroid Build Coastguard Worker return num_frames_; 221*795d594fSAndroid Build Coastguard Worker } 222*795d594fSAndroid Build Coastguard Worker GetFrameDepth()223*795d594fSAndroid Build Coastguard Worker size_t GetFrameDepth() const REQUIRES_SHARED(Locks::mutator_lock_) { 224*795d594fSAndroid Build Coastguard Worker return cur_depth_; 225*795d594fSAndroid Build Coastguard Worker } 226*795d594fSAndroid Build Coastguard Worker 227*795d594fSAndroid Build Coastguard Worker // Get the method and dex pc immediately after the one that's currently being visited. 228*795d594fSAndroid Build Coastguard Worker bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc) 229*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 230*795d594fSAndroid Build Coastguard Worker 231*795d594fSAndroid Build Coastguard Worker EXPORT bool GetVReg( 232*795d594fSAndroid Build Coastguard Worker ArtMethod* m, 233*795d594fSAndroid Build Coastguard Worker uint16_t vreg, 234*795d594fSAndroid Build Coastguard Worker VRegKind kind, 235*795d594fSAndroid Build Coastguard Worker uint32_t* val, 236*795d594fSAndroid Build Coastguard Worker std::optional<DexRegisterLocation> location = std::optional<DexRegisterLocation>(), 237*795d594fSAndroid Build Coastguard Worker bool need_full_register_list = false) const REQUIRES_SHARED(Locks::mutator_lock_); 238*795d594fSAndroid Build Coastguard Worker 239*795d594fSAndroid Build Coastguard Worker EXPORT bool GetVRegPair(ArtMethod* m, 240*795d594fSAndroid Build Coastguard Worker uint16_t vreg, 241*795d594fSAndroid Build Coastguard Worker VRegKind kind_lo, 242*795d594fSAndroid Build Coastguard Worker VRegKind kind_hi, 243*795d594fSAndroid Build Coastguard Worker uint64_t* val) const REQUIRES_SHARED(Locks::mutator_lock_); 244*795d594fSAndroid Build Coastguard Worker 245*795d594fSAndroid Build Coastguard Worker // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 246*795d594fSAndroid Build Coastguard Worker // is triggered to make the values effective. 247*795d594fSAndroid Build Coastguard Worker EXPORT bool SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) 248*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 249*795d594fSAndroid Build Coastguard Worker 250*795d594fSAndroid Build Coastguard Worker // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 251*795d594fSAndroid Build Coastguard Worker // is triggered to make the values effective. 252*795d594fSAndroid Build Coastguard Worker EXPORT bool SetVRegReference(ArtMethod* m, uint16_t vreg, ObjPtr<mirror::Object> new_value) 253*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 256*795d594fSAndroid Build Coastguard Worker // is triggered to make the values effective. 257*795d594fSAndroid Build Coastguard Worker EXPORT bool SetVRegPair(ArtMethod* m, 258*795d594fSAndroid Build Coastguard Worker uint16_t vreg, 259*795d594fSAndroid Build Coastguard Worker uint64_t new_value, 260*795d594fSAndroid Build Coastguard Worker VRegKind kind_lo, 261*795d594fSAndroid Build Coastguard Worker VRegKind kind_hi) REQUIRES_SHARED(Locks::mutator_lock_); 262*795d594fSAndroid Build Coastguard Worker 263*795d594fSAndroid Build Coastguard Worker uintptr_t* GetGPRAddress(uint32_t reg) const; 264*795d594fSAndroid Build Coastguard Worker 265*795d594fSAndroid Build Coastguard Worker uintptr_t GetReturnPc() const REQUIRES_SHARED(Locks::mutator_lock_); 266*795d594fSAndroid Build Coastguard Worker uintptr_t GetReturnPcAddr() const REQUIRES_SHARED(Locks::mutator_lock_); 267*795d594fSAndroid Build Coastguard Worker 268*795d594fSAndroid Build Coastguard Worker void SetReturnPc(uintptr_t new_ret_pc) REQUIRES_SHARED(Locks::mutator_lock_); 269*795d594fSAndroid Build Coastguard Worker IsInInlinedFrame()270*795d594fSAndroid Build Coastguard Worker bool IsInInlinedFrame() const { 271*795d594fSAndroid Build Coastguard Worker return !current_inline_frames_.empty(); 272*795d594fSAndroid Build Coastguard Worker } 273*795d594fSAndroid Build Coastguard Worker InlineDepth()274*795d594fSAndroid Build Coastguard Worker size_t InlineDepth() const { return current_inline_frames_.size(); } 275*795d594fSAndroid Build Coastguard Worker GetCurrentInlinedFrame()276*795d594fSAndroid Build Coastguard Worker InlineInfo GetCurrentInlinedFrame() const { 277*795d594fSAndroid Build Coastguard Worker return current_inline_frames_.back(); 278*795d594fSAndroid Build Coastguard Worker } 279*795d594fSAndroid Build Coastguard Worker GetCurrentInlinedFrames()280*795d594fSAndroid Build Coastguard Worker const BitTableRange<InlineInfo>& GetCurrentInlinedFrames() const { 281*795d594fSAndroid Build Coastguard Worker return current_inline_frames_; 282*795d594fSAndroid Build Coastguard Worker } 283*795d594fSAndroid Build Coastguard Worker GetCurrentQuickFramePc()284*795d594fSAndroid Build Coastguard Worker uintptr_t GetCurrentQuickFramePc() const { 285*795d594fSAndroid Build Coastguard Worker return cur_quick_frame_pc_; 286*795d594fSAndroid Build Coastguard Worker } 287*795d594fSAndroid Build Coastguard Worker GetCurrentQuickFrame()288*795d594fSAndroid Build Coastguard Worker ArtMethod** GetCurrentQuickFrame() const { 289*795d594fSAndroid Build Coastguard Worker return cur_quick_frame_; 290*795d594fSAndroid Build Coastguard Worker } 291*795d594fSAndroid Build Coastguard Worker GetCurrentShadowFrame()292*795d594fSAndroid Build Coastguard Worker ShadowFrame* GetCurrentShadowFrame() const { 293*795d594fSAndroid Build Coastguard Worker return cur_shadow_frame_; 294*795d594fSAndroid Build Coastguard Worker } 295*795d594fSAndroid Build Coastguard Worker 296*795d594fSAndroid Build Coastguard Worker std::string DescribeLocation() const REQUIRES_SHARED(Locks::mutator_lock_); 297*795d594fSAndroid Build Coastguard Worker 298*795d594fSAndroid Build Coastguard Worker EXPORT static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) 299*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 300*795d594fSAndroid Build Coastguard Worker 301*795d594fSAndroid Build Coastguard Worker static void DescribeStack(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_); 302*795d594fSAndroid Build Coastguard Worker GetCurrentOatQuickMethodHeader()303*795d594fSAndroid Build Coastguard Worker const OatQuickMethodHeader* GetCurrentOatQuickMethodHeader() const { 304*795d594fSAndroid Build Coastguard Worker return cur_oat_quick_method_header_; 305*795d594fSAndroid Build Coastguard Worker } 306*795d594fSAndroid Build Coastguard Worker 307*795d594fSAndroid Build Coastguard Worker QuickMethodFrameInfo GetCurrentQuickFrameInfo() const REQUIRES_SHARED(Locks::mutator_lock_); 308*795d594fSAndroid Build Coastguard Worker SetShouldDeoptimizeFlag(DeoptimizeFlagValue value)309*795d594fSAndroid Build Coastguard Worker void SetShouldDeoptimizeFlag(DeoptimizeFlagValue value) REQUIRES_SHARED(Locks::mutator_lock_) { 310*795d594fSAndroid Build Coastguard Worker uint8_t* should_deoptimize_addr = GetShouldDeoptimizeFlagAddr(); 311*795d594fSAndroid Build Coastguard Worker *should_deoptimize_addr = *should_deoptimize_addr | static_cast<uint8_t>(value); 312*795d594fSAndroid Build Coastguard Worker }; 313*795d594fSAndroid Build Coastguard Worker UnsetShouldDeoptimizeFlag(DeoptimizeFlagValue value)314*795d594fSAndroid Build Coastguard Worker void UnsetShouldDeoptimizeFlag(DeoptimizeFlagValue value) REQUIRES_SHARED(Locks::mutator_lock_) { 315*795d594fSAndroid Build Coastguard Worker uint8_t* should_deoptimize_addr = GetShouldDeoptimizeFlagAddr(); 316*795d594fSAndroid Build Coastguard Worker *should_deoptimize_addr = *should_deoptimize_addr & ~static_cast<uint8_t>(value); 317*795d594fSAndroid Build Coastguard Worker }; 318*795d594fSAndroid Build Coastguard Worker GetShouldDeoptimizeFlag()319*795d594fSAndroid Build Coastguard Worker uint8_t GetShouldDeoptimizeFlag() const REQUIRES_SHARED(Locks::mutator_lock_) { 320*795d594fSAndroid Build Coastguard Worker return *GetShouldDeoptimizeFlagAddr(); 321*795d594fSAndroid Build Coastguard Worker } 322*795d594fSAndroid Build Coastguard Worker ShouldForceDeoptForRedefinition()323*795d594fSAndroid Build Coastguard Worker bool ShouldForceDeoptForRedefinition() const REQUIRES_SHARED(Locks::mutator_lock_) { 324*795d594fSAndroid Build Coastguard Worker uint8_t should_deopt_flag = GetShouldDeoptimizeFlag(); 325*795d594fSAndroid Build Coastguard Worker return (should_deopt_flag & 326*795d594fSAndroid Build Coastguard Worker static_cast<uint8_t>(DeoptimizeFlagValue::kForceDeoptForRedefinition)) != 0; 327*795d594fSAndroid Build Coastguard Worker } 328*795d594fSAndroid Build Coastguard Worker 329*795d594fSAndroid Build Coastguard Worker // Return the number of dex register in the map from the outermost frame to the number of inlined 330*795d594fSAndroid Build Coastguard Worker // frames indicated by `depth`. If `depth` is 0, grab just the registers from the outermost level. 331*795d594fSAndroid Build Coastguard Worker // If it is greater than 0, grab as many inline frames as `depth` indicates. 332*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfRegisters(CodeInfo* code_info, int depth) const; 333*795d594fSAndroid Build Coastguard Worker 334*795d594fSAndroid Build Coastguard Worker private: 335*795d594fSAndroid Build Coastguard Worker // Private constructor known in the case that num_frames_ has already been computed. 336*795d594fSAndroid Build Coastguard Worker EXPORT StackVisitor(Thread* thread, 337*795d594fSAndroid Build Coastguard Worker Context* context, 338*795d594fSAndroid Build Coastguard Worker StackWalkKind walk_kind, 339*795d594fSAndroid Build Coastguard Worker size_t num_frames, 340*795d594fSAndroid Build Coastguard Worker bool check_suspended = true) REQUIRES_SHARED(Locks::mutator_lock_); 341*795d594fSAndroid Build Coastguard Worker IsAccessibleRegister(uint32_t reg,bool is_float)342*795d594fSAndroid Build Coastguard Worker bool IsAccessibleRegister(uint32_t reg, bool is_float) const { 343*795d594fSAndroid Build Coastguard Worker return is_float ? IsAccessibleFPR(reg) : IsAccessibleGPR(reg); 344*795d594fSAndroid Build Coastguard Worker } GetRegister(uint32_t reg,bool is_float)345*795d594fSAndroid Build Coastguard Worker uintptr_t GetRegister(uint32_t reg, bool is_float) const { 346*795d594fSAndroid Build Coastguard Worker DCHECK(IsAccessibleRegister(reg, is_float)); 347*795d594fSAndroid Build Coastguard Worker return is_float ? GetFPR(reg) : GetGPR(reg); 348*795d594fSAndroid Build Coastguard Worker } 349*795d594fSAndroid Build Coastguard Worker 350*795d594fSAndroid Build Coastguard Worker bool IsAccessibleGPR(uint32_t reg) const; 351*795d594fSAndroid Build Coastguard Worker uintptr_t GetGPR(uint32_t reg) const; 352*795d594fSAndroid Build Coastguard Worker 353*795d594fSAndroid Build Coastguard Worker bool IsAccessibleFPR(uint32_t reg) const; 354*795d594fSAndroid Build Coastguard Worker uintptr_t GetFPR(uint32_t reg) const; 355*795d594fSAndroid Build Coastguard Worker 356*795d594fSAndroid Build Coastguard Worker bool GetVRegFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind, uint32_t* val) const 357*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 358*795d594fSAndroid Build Coastguard Worker bool GetVRegFromOptimizedCode(ArtMethod* m, 359*795d594fSAndroid Build Coastguard Worker uint16_t vreg, 360*795d594fSAndroid Build Coastguard Worker VRegKind kind, 361*795d594fSAndroid Build Coastguard Worker uint32_t* val, 362*795d594fSAndroid Build Coastguard Worker bool need_full_register_list = false) const 363*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 364*795d594fSAndroid Build Coastguard Worker 365*795d594fSAndroid Build Coastguard Worker bool GetVRegPairFromDebuggerShadowFrame(uint16_t vreg, 366*795d594fSAndroid Build Coastguard Worker VRegKind kind_lo, 367*795d594fSAndroid Build Coastguard Worker VRegKind kind_hi, 368*795d594fSAndroid Build Coastguard Worker uint64_t* val) const 369*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 370*795d594fSAndroid Build Coastguard Worker bool GetVRegPairFromOptimizedCode(ArtMethod* m, 371*795d594fSAndroid Build Coastguard Worker uint16_t vreg, 372*795d594fSAndroid Build Coastguard Worker VRegKind kind_lo, 373*795d594fSAndroid Build Coastguard Worker VRegKind kind_hi, 374*795d594fSAndroid Build Coastguard Worker uint64_t* val) const 375*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 376*795d594fSAndroid Build Coastguard Worker bool GetVRegFromOptimizedCode(DexRegisterLocation location, uint32_t* val) const 377*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 378*795d594fSAndroid Build Coastguard Worker 379*795d594fSAndroid Build Coastguard Worker ShadowFrame* PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide) 380*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 381*795d594fSAndroid Build Coastguard Worker 382*795d594fSAndroid Build Coastguard Worker void ValidateFrame() const REQUIRES_SHARED(Locks::mutator_lock_); 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE CodeInfo* GetCurrentInlineInfo() const; 385*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE StackMap* GetCurrentStackMap() const; 386*795d594fSAndroid Build Coastguard Worker 387*795d594fSAndroid Build Coastguard Worker Thread* const thread_; 388*795d594fSAndroid Build Coastguard Worker const StackWalkKind walk_kind_; 389*795d594fSAndroid Build Coastguard Worker ShadowFrame* cur_shadow_frame_; 390*795d594fSAndroid Build Coastguard Worker ArtMethod** cur_quick_frame_; 391*795d594fSAndroid Build Coastguard Worker uintptr_t cur_quick_frame_pc_; 392*795d594fSAndroid Build Coastguard Worker const OatQuickMethodHeader* cur_oat_quick_method_header_; 393*795d594fSAndroid Build Coastguard Worker // Lazily computed, number of frames in the stack. 394*795d594fSAndroid Build Coastguard Worker size_t num_frames_; 395*795d594fSAndroid Build Coastguard Worker // Depth of the frame we're currently at. 396*795d594fSAndroid Build Coastguard Worker size_t cur_depth_; 397*795d594fSAndroid Build Coastguard Worker // Current inlined frames of the method we are currently at. 398*795d594fSAndroid Build Coastguard Worker // We keep poping frames from the end as we visit the frames. 399*795d594fSAndroid Build Coastguard Worker BitTableRange<InlineInfo> current_inline_frames_; 400*795d594fSAndroid Build Coastguard Worker 401*795d594fSAndroid Build Coastguard Worker // Cache the most recently decoded inline info data. 402*795d594fSAndroid Build Coastguard Worker // The 'current_inline_frames_' refers to this data, so we need to keep it alive anyway. 403*795d594fSAndroid Build Coastguard Worker // Marked mutable since the cache fields are updated from const getters. 404*795d594fSAndroid Build Coastguard Worker mutable std::pair<const OatQuickMethodHeader*, CodeInfo> cur_inline_info_; 405*795d594fSAndroid Build Coastguard Worker mutable std::pair<uintptr_t, StackMap> cur_stack_map_; 406*795d594fSAndroid Build Coastguard Worker 407*795d594fSAndroid Build Coastguard Worker uint8_t* GetShouldDeoptimizeFlagAddr() const REQUIRES_SHARED(Locks::mutator_lock_); 408*795d594fSAndroid Build Coastguard Worker 409*795d594fSAndroid Build Coastguard Worker protected: 410*795d594fSAndroid Build Coastguard Worker Context* const context_; 411*795d594fSAndroid Build Coastguard Worker const bool check_suspended_; 412*795d594fSAndroid Build Coastguard Worker }; 413*795d594fSAndroid Build Coastguard Worker 414*795d594fSAndroid Build Coastguard Worker } // namespace art 415*795d594fSAndroid Build Coastguard Worker 416*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_STACK_H_ 417