xref: /aosp_15_r20/art/runtime/stack.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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