xref: /aosp_15_r20/art/runtime/stack.cc (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 #include "stack.h"
18*795d594fSAndroid Build Coastguard Worker #include <limits>
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
23*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/callee_save_type.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/hex_dump.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/indenter.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
29*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
30*795d594fSAndroid Build Coastguard Worker #include "entrypoints/entrypoint_utils-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "entrypoints/quick/callee_save_frame.h"
32*795d594fSAndroid Build Coastguard Worker #include "entrypoints/runtime_asm_entrypoints.h"
33*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
34*795d594fSAndroid Build Coastguard Worker #include "gc/space/space-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "interpreter/mterp/nterp.h"
36*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
38*795d594fSAndroid Build Coastguard Worker #include "jit/jit_code_cache.h"
39*795d594fSAndroid Build Coastguard Worker #include "linear_alloc.h"
40*795d594fSAndroid Build Coastguard Worker #include "managed_stack.h"
41*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "nterp_helpers.h"
45*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h"
46*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "quick/quick_method_frame_info.h"
48*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
49*795d594fSAndroid Build Coastguard Worker #include "thread.h"
50*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker static constexpr bool kDebugStackWalk = false;
57*795d594fSAndroid Build Coastguard Worker 
StackVisitor(Thread * thread,Context * context,StackWalkKind walk_kind,bool check_suspended)58*795d594fSAndroid Build Coastguard Worker StackVisitor::StackVisitor(Thread* thread,
59*795d594fSAndroid Build Coastguard Worker                            Context* context,
60*795d594fSAndroid Build Coastguard Worker                            StackWalkKind walk_kind,
61*795d594fSAndroid Build Coastguard Worker                            bool check_suspended)
62*795d594fSAndroid Build Coastguard Worker     : StackVisitor(thread, context, walk_kind, 0, check_suspended) {}
63*795d594fSAndroid Build Coastguard Worker 
StackVisitor(Thread * thread,Context * context,StackWalkKind walk_kind,size_t num_frames,bool check_suspended)64*795d594fSAndroid Build Coastguard Worker StackVisitor::StackVisitor(Thread* thread,
65*795d594fSAndroid Build Coastguard Worker                            Context* context,
66*795d594fSAndroid Build Coastguard Worker                            StackWalkKind walk_kind,
67*795d594fSAndroid Build Coastguard Worker                            size_t num_frames,
68*795d594fSAndroid Build Coastguard Worker                            bool check_suspended)
69*795d594fSAndroid Build Coastguard Worker     : thread_(thread),
70*795d594fSAndroid Build Coastguard Worker       walk_kind_(walk_kind),
71*795d594fSAndroid Build Coastguard Worker       cur_shadow_frame_(nullptr),
72*795d594fSAndroid Build Coastguard Worker       cur_quick_frame_(nullptr),
73*795d594fSAndroid Build Coastguard Worker       cur_quick_frame_pc_(0),
74*795d594fSAndroid Build Coastguard Worker       cur_oat_quick_method_header_(nullptr),
75*795d594fSAndroid Build Coastguard Worker       num_frames_(num_frames),
76*795d594fSAndroid Build Coastguard Worker       cur_depth_(0),
77*795d594fSAndroid Build Coastguard Worker       cur_inline_info_(nullptr, CodeInfo()),
78*795d594fSAndroid Build Coastguard Worker       cur_stack_map_(0, StackMap()),
79*795d594fSAndroid Build Coastguard Worker       context_(context),
80*795d594fSAndroid Build Coastguard Worker       check_suspended_(check_suspended) {
81*795d594fSAndroid Build Coastguard Worker   if (check_suspended_) {
82*795d594fSAndroid Build Coastguard Worker     DCHECK(thread == Thread::Current() || thread->GetState() != ThreadState::kRunnable) << *thread;
83*795d594fSAndroid Build Coastguard Worker   }
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker 
GetCurrentInlineInfo() const86*795d594fSAndroid Build Coastguard Worker CodeInfo* StackVisitor::GetCurrentInlineInfo() const {
87*795d594fSAndroid Build Coastguard Worker   DCHECK(!(*cur_quick_frame_)->IsNative());
88*795d594fSAndroid Build Coastguard Worker   const OatQuickMethodHeader* header = GetCurrentOatQuickMethodHeader();
89*795d594fSAndroid Build Coastguard Worker   if (cur_inline_info_.first != header) {
90*795d594fSAndroid Build Coastguard Worker     cur_inline_info_ = std::make_pair(header, CodeInfo::DecodeInlineInfoOnly(header));
91*795d594fSAndroid Build Coastguard Worker   }
92*795d594fSAndroid Build Coastguard Worker   return &cur_inline_info_.second;
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker 
GetCurrentStackMap() const95*795d594fSAndroid Build Coastguard Worker StackMap* StackVisitor::GetCurrentStackMap() const {
96*795d594fSAndroid Build Coastguard Worker   DCHECK(!(*cur_quick_frame_)->IsNative());
97*795d594fSAndroid Build Coastguard Worker   const OatQuickMethodHeader* header = GetCurrentOatQuickMethodHeader();
98*795d594fSAndroid Build Coastguard Worker   if (cur_stack_map_.first != cur_quick_frame_pc_) {
99*795d594fSAndroid Build Coastguard Worker     uint32_t pc = header->NativeQuickPcOffset(cur_quick_frame_pc_);
100*795d594fSAndroid Build Coastguard Worker     cur_stack_map_ = std::make_pair(cur_quick_frame_pc_,
101*795d594fSAndroid Build Coastguard Worker                                     GetCurrentInlineInfo()->GetStackMapForNativePcOffset(pc));
102*795d594fSAndroid Build Coastguard Worker   }
103*795d594fSAndroid Build Coastguard Worker   return &cur_stack_map_.second;
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker 
GetMethod() const106*795d594fSAndroid Build Coastguard Worker ArtMethod* StackVisitor::GetMethod() const {
107*795d594fSAndroid Build Coastguard Worker   if (cur_shadow_frame_ != nullptr) {
108*795d594fSAndroid Build Coastguard Worker     return cur_shadow_frame_->GetMethod();
109*795d594fSAndroid Build Coastguard Worker   } else if (cur_quick_frame_ != nullptr) {
110*795d594fSAndroid Build Coastguard Worker     if (IsInInlinedFrame()) {
111*795d594fSAndroid Build Coastguard Worker       CodeInfo* code_info = GetCurrentInlineInfo();
112*795d594fSAndroid Build Coastguard Worker       DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
113*795d594fSAndroid Build Coastguard Worker       return GetResolvedMethod(*GetCurrentQuickFrame(), *code_info, current_inline_frames_);
114*795d594fSAndroid Build Coastguard Worker     } else {
115*795d594fSAndroid Build Coastguard Worker       return *cur_quick_frame_;
116*795d594fSAndroid Build Coastguard Worker     }
117*795d594fSAndroid Build Coastguard Worker   }
118*795d594fSAndroid Build Coastguard Worker   return nullptr;
119*795d594fSAndroid Build Coastguard Worker }
120*795d594fSAndroid Build Coastguard Worker 
GetDexPc(bool abort_on_failure) const121*795d594fSAndroid Build Coastguard Worker uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
122*795d594fSAndroid Build Coastguard Worker   if (cur_shadow_frame_ != nullptr) {
123*795d594fSAndroid Build Coastguard Worker     return cur_shadow_frame_->GetDexPC();
124*795d594fSAndroid Build Coastguard Worker   } else if (cur_quick_frame_ != nullptr) {
125*795d594fSAndroid Build Coastguard Worker     if (IsInInlinedFrame()) {
126*795d594fSAndroid Build Coastguard Worker       return current_inline_frames_.back().GetDexPc();
127*795d594fSAndroid Build Coastguard Worker     } else if (cur_oat_quick_method_header_ == nullptr) {
128*795d594fSAndroid Build Coastguard Worker       return dex::kDexNoIndex;
129*795d594fSAndroid Build Coastguard Worker     } else if ((*GetCurrentQuickFrame())->IsNative()) {
130*795d594fSAndroid Build Coastguard Worker       return cur_oat_quick_method_header_->ToDexPc(
131*795d594fSAndroid Build Coastguard Worker           GetCurrentQuickFrame(), cur_quick_frame_pc_, abort_on_failure);
132*795d594fSAndroid Build Coastguard Worker     } else if (cur_oat_quick_method_header_->IsOptimized()) {
133*795d594fSAndroid Build Coastguard Worker       StackMap* stack_map = GetCurrentStackMap();
134*795d594fSAndroid Build Coastguard Worker       if (!stack_map->IsValid()) {
135*795d594fSAndroid Build Coastguard Worker         // Debugging code for b/361916648.
136*795d594fSAndroid Build Coastguard Worker         CodeInfo code_info(cur_oat_quick_method_header_);
137*795d594fSAndroid Build Coastguard Worker         std::stringstream os;
138*795d594fSAndroid Build Coastguard Worker         VariableIndentationOutputStream vios(&os);
139*795d594fSAndroid Build Coastguard Worker         code_info.Dump(&vios, /* code_offset= */ 0u, /* verbose= */ true, kRuntimeQuickCodeISA);
140*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << os.str() << '\n'
141*795d594fSAndroid Build Coastguard Worker                    << "StackMap not found for "
142*795d594fSAndroid Build Coastguard Worker                    << std::hex << cur_quick_frame_pc_ << " in "
143*795d594fSAndroid Build Coastguard Worker                    << GetMethod()->PrettyMethod()
144*795d594fSAndroid Build Coastguard Worker                    << " @" << std::hex
145*795d594fSAndroid Build Coastguard Worker                    << reinterpret_cast<uintptr_t>(cur_oat_quick_method_header_->GetCode());
146*795d594fSAndroid Build Coastguard Worker       }
147*795d594fSAndroid Build Coastguard Worker       return stack_map->GetDexPc();
148*795d594fSAndroid Build Coastguard Worker     } else {
149*795d594fSAndroid Build Coastguard Worker       DCHECK(cur_oat_quick_method_header_->IsNterpMethodHeader());
150*795d594fSAndroid Build Coastguard Worker       return NterpGetDexPC(cur_quick_frame_);
151*795d594fSAndroid Build Coastguard Worker     }
152*795d594fSAndroid Build Coastguard Worker   } else {
153*795d594fSAndroid Build Coastguard Worker     return 0;
154*795d594fSAndroid Build Coastguard Worker   }
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker 
ComputeDexPcList(uint32_t handler_dex_pc) const157*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> StackVisitor::ComputeDexPcList(uint32_t handler_dex_pc) const {
158*795d594fSAndroid Build Coastguard Worker   std::vector<uint32_t> result;
159*795d594fSAndroid Build Coastguard Worker   if (cur_shadow_frame_ == nullptr && cur_quick_frame_ != nullptr && IsInInlinedFrame()) {
160*795d594fSAndroid Build Coastguard Worker     const BitTableRange<InlineInfo>& infos = current_inline_frames_;
161*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(infos.size(), 0u);
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker     // Outermost dex_pc.
164*795d594fSAndroid Build Coastguard Worker     result.push_back(GetCurrentStackMap()->GetDexPc());
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker     // The mid dex_pcs. Note that we skip the last one since we want to change that for
167*795d594fSAndroid Build Coastguard Worker     // `handler_dex_pc`.
168*795d594fSAndroid Build Coastguard Worker     for (size_t index = 0; index < infos.size() - 1; ++index) {
169*795d594fSAndroid Build Coastguard Worker       result.push_back(infos[index].GetDexPc());
170*795d594fSAndroid Build Coastguard Worker     }
171*795d594fSAndroid Build Coastguard Worker   }
172*795d594fSAndroid Build Coastguard Worker 
173*795d594fSAndroid Build Coastguard Worker   // The innermost dex_pc has to be the handler dex_pc. In the case of no inline frames, it will be
174*795d594fSAndroid Build Coastguard Worker   // just the one dex_pc. In the case of inlining we will be replacing the innermost InlineInfo's
175*795d594fSAndroid Build Coastguard Worker   // dex_pc with this one.
176*795d594fSAndroid Build Coastguard Worker   result.push_back(handler_dex_pc);
177*795d594fSAndroid Build Coastguard Worker   return result;
178*795d594fSAndroid Build Coastguard Worker }
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp)
181*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
182*795d594fSAndroid Build Coastguard Worker 
GetThisObject() const183*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> StackVisitor::GetThisObject() const {
184*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
185*795d594fSAndroid Build Coastguard Worker   ArtMethod* m = GetMethod();
186*795d594fSAndroid Build Coastguard Worker   if (m->IsStatic()) {
187*795d594fSAndroid Build Coastguard Worker     return nullptr;
188*795d594fSAndroid Build Coastguard Worker   } else if (m->IsNative()) {
189*795d594fSAndroid Build Coastguard Worker     if (cur_quick_frame_ != nullptr) {
190*795d594fSAndroid Build Coastguard Worker       // The `this` reference is stored in the first out vreg in the caller's frame.
191*795d594fSAndroid Build Coastguard Worker       const size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
192*795d594fSAndroid Build Coastguard Worker       auto* stack_ref = reinterpret_cast<StackReference<mirror::Object>*>(
193*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<uint8_t*>(cur_quick_frame_) + frame_size + sizeof(ArtMethod*));
194*795d594fSAndroid Build Coastguard Worker       return stack_ref->AsMirrorPtr();
195*795d594fSAndroid Build Coastguard Worker     } else {
196*795d594fSAndroid Build Coastguard Worker       return cur_shadow_frame_->GetVRegReference(0);
197*795d594fSAndroid Build Coastguard Worker     }
198*795d594fSAndroid Build Coastguard Worker   } else if (m->IsProxyMethod()) {
199*795d594fSAndroid Build Coastguard Worker     if (cur_quick_frame_ != nullptr) {
200*795d594fSAndroid Build Coastguard Worker       return artQuickGetProxyThisObject(cur_quick_frame_);
201*795d594fSAndroid Build Coastguard Worker     } else {
202*795d594fSAndroid Build Coastguard Worker       return cur_shadow_frame_->GetVRegReference(0);
203*795d594fSAndroid Build Coastguard Worker     }
204*795d594fSAndroid Build Coastguard Worker   } else {
205*795d594fSAndroid Build Coastguard Worker     CodeItemDataAccessor accessor(m->DexInstructionData());
206*795d594fSAndroid Build Coastguard Worker     if (!accessor.HasCodeItem()) {
207*795d594fSAndroid Build Coastguard Worker       UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method: "
208*795d594fSAndroid Build Coastguard Worker           << ArtMethod::PrettyMethod(m);
209*795d594fSAndroid Build Coastguard Worker       return nullptr;
210*795d594fSAndroid Build Coastguard Worker     } else {
211*795d594fSAndroid Build Coastguard Worker       uint16_t reg = accessor.RegistersSize() - accessor.InsSize();
212*795d594fSAndroid Build Coastguard Worker       uint32_t value = 0;
213*795d594fSAndroid Build Coastguard Worker       if (!GetVReg(m, reg, kReferenceVReg, &value)) {
214*795d594fSAndroid Build Coastguard Worker         return nullptr;
215*795d594fSAndroid Build Coastguard Worker       }
216*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<mirror::Object*>(value);
217*795d594fSAndroid Build Coastguard Worker     }
218*795d594fSAndroid Build Coastguard Worker   }
219*795d594fSAndroid Build Coastguard Worker }
220*795d594fSAndroid Build Coastguard Worker 
GetNativePcOffset() const221*795d594fSAndroid Build Coastguard Worker size_t StackVisitor::GetNativePcOffset() const {
222*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsShadowFrame());
223*795d594fSAndroid Build Coastguard Worker   return GetCurrentOatQuickMethodHeader()->NativeQuickPcOffset(cur_quick_frame_pc_);
224*795d594fSAndroid Build Coastguard Worker }
225*795d594fSAndroid Build Coastguard Worker 
GetVRegFromDebuggerShadowFrame(uint16_t vreg,VRegKind kind,uint32_t * val) const226*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegFromDebuggerShadowFrame(uint16_t vreg,
227*795d594fSAndroid Build Coastguard Worker                                                   VRegKind kind,
228*795d594fSAndroid Build Coastguard Worker                                                   uint32_t* val) const {
229*795d594fSAndroid Build Coastguard Worker   size_t frame_id = const_cast<StackVisitor*>(this)->GetFrameId();
230*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = thread_->FindDebuggerShadowFrame(frame_id);
231*795d594fSAndroid Build Coastguard Worker   if (shadow_frame != nullptr) {
232*795d594fSAndroid Build Coastguard Worker     bool* updated_vreg_flags = thread_->GetUpdatedVRegFlags(frame_id);
233*795d594fSAndroid Build Coastguard Worker     DCHECK(updated_vreg_flags != nullptr);
234*795d594fSAndroid Build Coastguard Worker     if (updated_vreg_flags[vreg]) {
235*795d594fSAndroid Build Coastguard Worker       // Value is set by the debugger.
236*795d594fSAndroid Build Coastguard Worker       if (kind == kReferenceVReg) {
237*795d594fSAndroid Build Coastguard Worker         *val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
238*795d594fSAndroid Build Coastguard Worker             shadow_frame->GetVRegReference(vreg)));
239*795d594fSAndroid Build Coastguard Worker       } else {
240*795d594fSAndroid Build Coastguard Worker         *val = shadow_frame->GetVReg(vreg);
241*795d594fSAndroid Build Coastguard Worker       }
242*795d594fSAndroid Build Coastguard Worker       return true;
243*795d594fSAndroid Build Coastguard Worker     }
244*795d594fSAndroid Build Coastguard Worker   }
245*795d594fSAndroid Build Coastguard Worker   // No value is set by the debugger.
246*795d594fSAndroid Build Coastguard Worker   return false;
247*795d594fSAndroid Build Coastguard Worker }
248*795d594fSAndroid Build Coastguard Worker 
GetVReg(ArtMethod * m,uint16_t vreg,VRegKind kind,uint32_t * val,std::optional<DexRegisterLocation> location,bool need_full_register_list) const249*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVReg(ArtMethod* m,
250*795d594fSAndroid Build Coastguard Worker                            uint16_t vreg,
251*795d594fSAndroid Build Coastguard Worker                            VRegKind kind,
252*795d594fSAndroid Build Coastguard Worker                            uint32_t* val,
253*795d594fSAndroid Build Coastguard Worker                            std::optional<DexRegisterLocation> location,
254*795d594fSAndroid Build Coastguard Worker                            bool need_full_register_list) const {
255*795d594fSAndroid Build Coastguard Worker   if (cur_quick_frame_ != nullptr) {
256*795d594fSAndroid Build Coastguard Worker     DCHECK(context_ != nullptr);  // You can't reliably read registers without a context.
257*795d594fSAndroid Build Coastguard Worker     DCHECK(m == GetMethod());
258*795d594fSAndroid Build Coastguard Worker     // Check if there is value set by the debugger.
259*795d594fSAndroid Build Coastguard Worker     if (GetVRegFromDebuggerShadowFrame(vreg, kind, val)) {
260*795d594fSAndroid Build Coastguard Worker       return true;
261*795d594fSAndroid Build Coastguard Worker     }
262*795d594fSAndroid Build Coastguard Worker     bool result = false;
263*795d594fSAndroid Build Coastguard Worker     if (cur_oat_quick_method_header_->IsNterpMethodHeader()) {
264*795d594fSAndroid Build Coastguard Worker       result = true;
265*795d594fSAndroid Build Coastguard Worker       *val = (kind == kReferenceVReg)
266*795d594fSAndroid Build Coastguard Worker           ? NterpGetVRegReference(cur_quick_frame_, vreg)
267*795d594fSAndroid Build Coastguard Worker           : NterpGetVReg(cur_quick_frame_, vreg);
268*795d594fSAndroid Build Coastguard Worker     } else {
269*795d594fSAndroid Build Coastguard Worker       DCHECK(cur_oat_quick_method_header_->IsOptimized());
270*795d594fSAndroid Build Coastguard Worker       if (location.has_value() && kind != kReferenceVReg) {
271*795d594fSAndroid Build Coastguard Worker         uint32_t val2 = *val;
272*795d594fSAndroid Build Coastguard Worker         // The caller already known the register location, so we can use the faster overload
273*795d594fSAndroid Build Coastguard Worker         // which does not decode the stack maps.
274*795d594fSAndroid Build Coastguard Worker         result = GetVRegFromOptimizedCode(location.value(), val);
275*795d594fSAndroid Build Coastguard Worker         // Compare to the slower overload.
276*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(result, GetVRegFromOptimizedCode(m, vreg, kind, &val2, need_full_register_list));
277*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(*val, val2);
278*795d594fSAndroid Build Coastguard Worker       } else {
279*795d594fSAndroid Build Coastguard Worker         result = GetVRegFromOptimizedCode(m, vreg, kind, val, need_full_register_list);
280*795d594fSAndroid Build Coastguard Worker       }
281*795d594fSAndroid Build Coastguard Worker     }
282*795d594fSAndroid Build Coastguard Worker     if (kind == kReferenceVReg) {
283*795d594fSAndroid Build Coastguard Worker       // Perform a read barrier in case we are in a different thread and GC is ongoing.
284*795d594fSAndroid Build Coastguard Worker       mirror::Object* out = reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(*val));
285*795d594fSAndroid Build Coastguard Worker       uintptr_t ptr_out = reinterpret_cast<uintptr_t>(GcRoot<mirror::Object>(out).Read());
286*795d594fSAndroid Build Coastguard Worker       DCHECK_LT(ptr_out, std::numeric_limits<uint32_t>::max());
287*795d594fSAndroid Build Coastguard Worker       *val = static_cast<uint32_t>(ptr_out);
288*795d594fSAndroid Build Coastguard Worker     }
289*795d594fSAndroid Build Coastguard Worker     return result;
290*795d594fSAndroid Build Coastguard Worker   } else {
291*795d594fSAndroid Build Coastguard Worker     DCHECK(cur_shadow_frame_ != nullptr);
292*795d594fSAndroid Build Coastguard Worker     if (kind == kReferenceVReg) {
293*795d594fSAndroid Build Coastguard Worker       *val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
294*795d594fSAndroid Build Coastguard Worker           cur_shadow_frame_->GetVRegReference(vreg)));
295*795d594fSAndroid Build Coastguard Worker     } else {
296*795d594fSAndroid Build Coastguard Worker       *val = cur_shadow_frame_->GetVReg(vreg);
297*795d594fSAndroid Build Coastguard Worker     }
298*795d594fSAndroid Build Coastguard Worker     return true;
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker 
GetNumberOfRegisters(CodeInfo * code_info,int depth) const302*795d594fSAndroid Build Coastguard Worker size_t StackVisitor::GetNumberOfRegisters(CodeInfo* code_info, int depth) const {
303*795d594fSAndroid Build Coastguard Worker   return depth == 0
304*795d594fSAndroid Build Coastguard Worker     ? code_info->GetNumberOfDexRegisters()
305*795d594fSAndroid Build Coastguard Worker     : current_inline_frames_[depth - 1].GetNumberOfDexRegisters();
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker 
GetVRegFromOptimizedCode(ArtMethod * m,uint16_t vreg,VRegKind kind,uint32_t * val,bool need_full_register_list) const308*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m,
309*795d594fSAndroid Build Coastguard Worker                                             uint16_t vreg,
310*795d594fSAndroid Build Coastguard Worker                                             VRegKind kind,
311*795d594fSAndroid Build Coastguard Worker                                             uint32_t* val,
312*795d594fSAndroid Build Coastguard Worker                                             bool need_full_register_list) const {
313*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(m, GetMethod());
314*795d594fSAndroid Build Coastguard Worker   // Can't be null or how would we compile its instructions?
315*795d594fSAndroid Build Coastguard Worker   DCHECK(m->GetCodeItem() != nullptr) << m->PrettyMethod();
316*795d594fSAndroid Build Coastguard Worker   const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
317*795d594fSAndroid Build Coastguard Worker   CodeInfo code_info(method_header);
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc_);
320*795d594fSAndroid Build Coastguard Worker   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
321*795d594fSAndroid Build Coastguard Worker   DCHECK(stack_map.IsValid());
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker   DexRegisterMap dex_register_map = (IsInInlinedFrame() && !need_full_register_list)
324*795d594fSAndroid Build Coastguard Worker     ? code_info.GetInlineDexRegisterMapOf(stack_map, current_inline_frames_.back())
325*795d594fSAndroid Build Coastguard Worker     : code_info.GetDexRegisterMapOf(stack_map,
326*795d594fSAndroid Build Coastguard Worker                                     /* first= */ 0,
327*795d594fSAndroid Build Coastguard Worker                                     GetNumberOfRegisters(&code_info, InlineDepth()));
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker   if (dex_register_map.empty()) {
330*795d594fSAndroid Build Coastguard Worker     return false;
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker 
333*795d594fSAndroid Build Coastguard Worker   const size_t number_of_dex_registers = dex_register_map.size();
334*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(vreg, number_of_dex_registers);
335*795d594fSAndroid Build Coastguard Worker   DexRegisterLocation::Kind location_kind = dex_register_map[vreg].GetKind();
336*795d594fSAndroid Build Coastguard Worker   switch (location_kind) {
337*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInStack: {
338*795d594fSAndroid Build Coastguard Worker       const int32_t offset = dex_register_map[vreg].GetStackOffsetInBytes();
339*795d594fSAndroid Build Coastguard Worker       BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
340*795d594fSAndroid Build Coastguard Worker       if (kind == kReferenceVReg && !stack_mask.LoadBit(offset / kFrameSlotSize)) {
341*795d594fSAndroid Build Coastguard Worker         return false;
342*795d594fSAndroid Build Coastguard Worker       }
343*795d594fSAndroid Build Coastguard Worker       const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
344*795d594fSAndroid Build Coastguard Worker       *val = *reinterpret_cast<const uint32_t*>(addr);
345*795d594fSAndroid Build Coastguard Worker       return true;
346*795d594fSAndroid Build Coastguard Worker     }
347*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInRegister: {
348*795d594fSAndroid Build Coastguard Worker       uint32_t register_mask = code_info.GetRegisterMaskOf(stack_map);
349*795d594fSAndroid Build Coastguard Worker       uint32_t reg = dex_register_map[vreg].GetMachineRegister();
350*795d594fSAndroid Build Coastguard Worker       if (kind == kReferenceVReg && !(register_mask & (1 << reg))) {
351*795d594fSAndroid Build Coastguard Worker         return false;
352*795d594fSAndroid Build Coastguard Worker       }
353*795d594fSAndroid Build Coastguard Worker       return GetRegisterIfAccessible(reg, location_kind, val);
354*795d594fSAndroid Build Coastguard Worker     }
355*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInRegisterHigh:
356*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInFpuRegister:
357*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
358*795d594fSAndroid Build Coastguard Worker       if (kind == kReferenceVReg) {
359*795d594fSAndroid Build Coastguard Worker         return false;
360*795d594fSAndroid Build Coastguard Worker       }
361*795d594fSAndroid Build Coastguard Worker       uint32_t reg = dex_register_map[vreg].GetMachineRegister();
362*795d594fSAndroid Build Coastguard Worker       return GetRegisterIfAccessible(reg, location_kind, val);
363*795d594fSAndroid Build Coastguard Worker     }
364*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kConstant: {
365*795d594fSAndroid Build Coastguard Worker       uint32_t result = dex_register_map[vreg].GetConstant();
366*795d594fSAndroid Build Coastguard Worker       if (kind == kReferenceVReg && result != 0) {
367*795d594fSAndroid Build Coastguard Worker         return false;
368*795d594fSAndroid Build Coastguard Worker       }
369*795d594fSAndroid Build Coastguard Worker       *val = result;
370*795d594fSAndroid Build Coastguard Worker       return true;
371*795d594fSAndroid Build Coastguard Worker     }
372*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kNone:
373*795d594fSAndroid Build Coastguard Worker       return false;
374*795d594fSAndroid Build Coastguard Worker     default:
375*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unexpected location kind " << dex_register_map[vreg].GetKind();
376*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
377*795d594fSAndroid Build Coastguard Worker   }
378*795d594fSAndroid Build Coastguard Worker }
379*795d594fSAndroid Build Coastguard Worker 
GetVRegFromOptimizedCode(DexRegisterLocation location,uint32_t * val) const380*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegFromOptimizedCode(DexRegisterLocation location, uint32_t* val) const {
381*795d594fSAndroid Build Coastguard Worker   switch (location.GetKind()) {
382*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInvalid:
383*795d594fSAndroid Build Coastguard Worker       break;
384*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInStack: {
385*795d594fSAndroid Build Coastguard Worker       const uint8_t* sp = reinterpret_cast<const uint8_t*>(cur_quick_frame_);
386*795d594fSAndroid Build Coastguard Worker       *val = *reinterpret_cast<const uint32_t*>(sp + location.GetStackOffsetInBytes());
387*795d594fSAndroid Build Coastguard Worker       return true;
388*795d594fSAndroid Build Coastguard Worker     }
389*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInRegister:
390*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInRegisterHigh:
391*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInFpuRegister:
392*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kInFpuRegisterHigh:
393*795d594fSAndroid Build Coastguard Worker       return GetRegisterIfAccessible(location.GetMachineRegister(), location.GetKind(), val);
394*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kConstant:
395*795d594fSAndroid Build Coastguard Worker       *val = location.GetConstant();
396*795d594fSAndroid Build Coastguard Worker       return true;
397*795d594fSAndroid Build Coastguard Worker     case DexRegisterLocation::Kind::kNone:
398*795d594fSAndroid Build Coastguard Worker       return false;
399*795d594fSAndroid Build Coastguard Worker   }
400*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Unexpected location kind " << location.GetKind();
401*795d594fSAndroid Build Coastguard Worker   UNREACHABLE();
402*795d594fSAndroid Build Coastguard Worker }
403*795d594fSAndroid Build Coastguard Worker 
GetRegisterIfAccessible(uint32_t reg,DexRegisterLocation::Kind location_kind,uint32_t * val) const404*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetRegisterIfAccessible(uint32_t reg,
405*795d594fSAndroid Build Coastguard Worker                                            DexRegisterLocation::Kind location_kind,
406*795d594fSAndroid Build Coastguard Worker                                            uint32_t* val) const {
407*795d594fSAndroid Build Coastguard Worker   const bool is_float = (location_kind == DexRegisterLocation::Kind::kInFpuRegister) ||
408*795d594fSAndroid Build Coastguard Worker                         (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh);
409*795d594fSAndroid Build Coastguard Worker 
410*795d594fSAndroid Build Coastguard Worker   if (kRuntimeQuickCodeISA == InstructionSet::kX86 && is_float) {
411*795d594fSAndroid Build Coastguard Worker     // X86 float registers are 64-bit and each XMM register is provided as two separate
412*795d594fSAndroid Build Coastguard Worker     // 32-bit registers by the context.
413*795d594fSAndroid Build Coastguard Worker     reg = (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh)
414*795d594fSAndroid Build Coastguard Worker         ? (2 * reg + 1)
415*795d594fSAndroid Build Coastguard Worker         : (2 * reg);
416*795d594fSAndroid Build Coastguard Worker   }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker   if (!IsAccessibleRegister(reg, is_float)) {
419*795d594fSAndroid Build Coastguard Worker     return false;
420*795d594fSAndroid Build Coastguard Worker   }
421*795d594fSAndroid Build Coastguard Worker   uintptr_t ptr_val = GetRegister(reg, is_float);
422*795d594fSAndroid Build Coastguard Worker   const bool target64 = Is64BitInstructionSet(kRuntimeQuickCodeISA);
423*795d594fSAndroid Build Coastguard Worker   if (target64) {
424*795d594fSAndroid Build Coastguard Worker     const bool is_high = (location_kind == DexRegisterLocation::Kind::kInRegisterHigh) ||
425*795d594fSAndroid Build Coastguard Worker                          (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh);
426*795d594fSAndroid Build Coastguard Worker     int64_t value_long = static_cast<int64_t>(ptr_val);
427*795d594fSAndroid Build Coastguard Worker     ptr_val = static_cast<uintptr_t>(is_high ? High32Bits(value_long) : Low32Bits(value_long));
428*795d594fSAndroid Build Coastguard Worker   }
429*795d594fSAndroid Build Coastguard Worker   *val = ptr_val;
430*795d594fSAndroid Build Coastguard Worker   return true;
431*795d594fSAndroid Build Coastguard Worker }
432*795d594fSAndroid Build Coastguard Worker 
GetVRegPairFromDebuggerShadowFrame(uint16_t vreg,VRegKind kind_lo,VRegKind kind_hi,uint64_t * val) const433*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegPairFromDebuggerShadowFrame(uint16_t vreg,
434*795d594fSAndroid Build Coastguard Worker                                                       VRegKind kind_lo,
435*795d594fSAndroid Build Coastguard Worker                                                       VRegKind kind_hi,
436*795d594fSAndroid Build Coastguard Worker                                                       uint64_t* val) const {
437*795d594fSAndroid Build Coastguard Worker   uint32_t low_32bits;
438*795d594fSAndroid Build Coastguard Worker   uint32_t high_32bits;
439*795d594fSAndroid Build Coastguard Worker   bool success = GetVRegFromDebuggerShadowFrame(vreg, kind_lo, &low_32bits);
440*795d594fSAndroid Build Coastguard Worker   success &= GetVRegFromDebuggerShadowFrame(vreg + 1, kind_hi, &high_32bits);
441*795d594fSAndroid Build Coastguard Worker   if (success) {
442*795d594fSAndroid Build Coastguard Worker     *val = (static_cast<uint64_t>(high_32bits) << 32) | static_cast<uint64_t>(low_32bits);
443*795d594fSAndroid Build Coastguard Worker   }
444*795d594fSAndroid Build Coastguard Worker   return success;
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker 
GetVRegPair(ArtMethod * m,uint16_t vreg,VRegKind kind_lo,VRegKind kind_hi,uint64_t * val) const447*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
448*795d594fSAndroid Build Coastguard Worker                                VRegKind kind_hi, uint64_t* val) const {
449*795d594fSAndroid Build Coastguard Worker   if (kind_lo == kLongLoVReg) {
450*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(kind_hi, kLongHiVReg);
451*795d594fSAndroid Build Coastguard Worker   } else if (kind_lo == kDoubleLoVReg) {
452*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(kind_hi, kDoubleHiVReg);
453*795d594fSAndroid Build Coastguard Worker   } else {
454*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Expected long or double: kind_lo=" << kind_lo << ", kind_hi=" << kind_hi;
455*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
456*795d594fSAndroid Build Coastguard Worker   }
457*795d594fSAndroid Build Coastguard Worker   // Check if there is value set by the debugger.
458*795d594fSAndroid Build Coastguard Worker   if (GetVRegPairFromDebuggerShadowFrame(vreg, kind_lo, kind_hi, val)) {
459*795d594fSAndroid Build Coastguard Worker     return true;
460*795d594fSAndroid Build Coastguard Worker   }
461*795d594fSAndroid Build Coastguard Worker   if (cur_quick_frame_ == nullptr) {
462*795d594fSAndroid Build Coastguard Worker     DCHECK(cur_shadow_frame_ != nullptr);
463*795d594fSAndroid Build Coastguard Worker     *val = cur_shadow_frame_->GetVRegLong(vreg);
464*795d594fSAndroid Build Coastguard Worker     return true;
465*795d594fSAndroid Build Coastguard Worker   }
466*795d594fSAndroid Build Coastguard Worker   if (cur_oat_quick_method_header_->IsNterpMethodHeader()) {
467*795d594fSAndroid Build Coastguard Worker     uint64_t val_lo = NterpGetVReg(cur_quick_frame_, vreg);
468*795d594fSAndroid Build Coastguard Worker     uint64_t val_hi = NterpGetVReg(cur_quick_frame_, vreg + 1);
469*795d594fSAndroid Build Coastguard Worker     *val = (val_hi << 32) + val_lo;
470*795d594fSAndroid Build Coastguard Worker     return true;
471*795d594fSAndroid Build Coastguard Worker   }
472*795d594fSAndroid Build Coastguard Worker 
473*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);  // You can't reliably read registers without a context.
474*795d594fSAndroid Build Coastguard Worker   DCHECK(m == GetMethod());
475*795d594fSAndroid Build Coastguard Worker   DCHECK(cur_oat_quick_method_header_->IsOptimized());
476*795d594fSAndroid Build Coastguard Worker   return GetVRegPairFromOptimizedCode(m, vreg, kind_lo, kind_hi, val);
477*795d594fSAndroid Build Coastguard Worker }
478*795d594fSAndroid Build Coastguard Worker 
GetVRegPairFromOptimizedCode(ArtMethod * m,uint16_t vreg,VRegKind kind_lo,VRegKind kind_hi,uint64_t * val) const479*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg,
480*795d594fSAndroid Build Coastguard Worker                                                 VRegKind kind_lo, VRegKind kind_hi,
481*795d594fSAndroid Build Coastguard Worker                                                 uint64_t* val) const {
482*795d594fSAndroid Build Coastguard Worker   uint32_t low_32bits;
483*795d594fSAndroid Build Coastguard Worker   uint32_t high_32bits;
484*795d594fSAndroid Build Coastguard Worker   bool success = GetVRegFromOptimizedCode(m, vreg, kind_lo, &low_32bits);
485*795d594fSAndroid Build Coastguard Worker   success &= GetVRegFromOptimizedCode(m, vreg + 1, kind_hi, &high_32bits);
486*795d594fSAndroid Build Coastguard Worker   if (success) {
487*795d594fSAndroid Build Coastguard Worker     *val = (static_cast<uint64_t>(high_32bits) << 32) | static_cast<uint64_t>(low_32bits);
488*795d594fSAndroid Build Coastguard Worker   }
489*795d594fSAndroid Build Coastguard Worker   return success;
490*795d594fSAndroid Build Coastguard Worker }
491*795d594fSAndroid Build Coastguard Worker 
PrepareSetVReg(ArtMethod * m,uint16_t vreg,bool wide)492*795d594fSAndroid Build Coastguard Worker ShadowFrame* StackVisitor::PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide) {
493*795d594fSAndroid Build Coastguard Worker   CodeItemDataAccessor accessor(m->DexInstructionData());
494*795d594fSAndroid Build Coastguard Worker   if (!accessor.HasCodeItem()) {
495*795d594fSAndroid Build Coastguard Worker     return nullptr;
496*795d594fSAndroid Build Coastguard Worker   }
497*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = GetCurrentShadowFrame();
498*795d594fSAndroid Build Coastguard Worker   if (shadow_frame == nullptr) {
499*795d594fSAndroid Build Coastguard Worker     // This is a compiled frame: we must prepare and update a shadow frame that will
500*795d594fSAndroid Build Coastguard Worker     // be executed by the interpreter after deoptimization of the stack.
501*795d594fSAndroid Build Coastguard Worker     const size_t frame_id = GetFrameId();
502*795d594fSAndroid Build Coastguard Worker     const uint16_t num_regs = accessor.RegistersSize();
503*795d594fSAndroid Build Coastguard Worker     shadow_frame = thread_->FindOrCreateDebuggerShadowFrame(frame_id, num_regs, m, GetDexPc());
504*795d594fSAndroid Build Coastguard Worker     CHECK(shadow_frame != nullptr);
505*795d594fSAndroid Build Coastguard Worker     // Remember the vreg(s) has been set for debugging and must not be overwritten by the
506*795d594fSAndroid Build Coastguard Worker     // original value during deoptimization of the stack.
507*795d594fSAndroid Build Coastguard Worker     thread_->GetUpdatedVRegFlags(frame_id)[vreg] = true;
508*795d594fSAndroid Build Coastguard Worker     if (wide) {
509*795d594fSAndroid Build Coastguard Worker       thread_->GetUpdatedVRegFlags(frame_id)[vreg + 1] = true;
510*795d594fSAndroid Build Coastguard Worker     }
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker   return shadow_frame;
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker 
SetVReg(ArtMethod * m,uint16_t vreg,uint32_t new_value,VRegKind kind)515*795d594fSAndroid Build Coastguard Worker bool StackVisitor::SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) {
516*795d594fSAndroid Build Coastguard Worker   DCHECK(kind == kIntVReg || kind == kFloatVReg);
517*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ false);
518*795d594fSAndroid Build Coastguard Worker   if (shadow_frame == nullptr) {
519*795d594fSAndroid Build Coastguard Worker     return false;
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker   shadow_frame->SetVReg(vreg, new_value);
522*795d594fSAndroid Build Coastguard Worker   return true;
523*795d594fSAndroid Build Coastguard Worker }
524*795d594fSAndroid Build Coastguard Worker 
SetVRegReference(ArtMethod * m,uint16_t vreg,ObjPtr<mirror::Object> new_value)525*795d594fSAndroid Build Coastguard Worker bool StackVisitor::SetVRegReference(ArtMethod* m, uint16_t vreg, ObjPtr<mirror::Object> new_value) {
526*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ false);
527*795d594fSAndroid Build Coastguard Worker   if (shadow_frame == nullptr) {
528*795d594fSAndroid Build Coastguard Worker     return false;
529*795d594fSAndroid Build Coastguard Worker   }
530*795d594fSAndroid Build Coastguard Worker   shadow_frame->SetVRegReference(vreg, new_value);
531*795d594fSAndroid Build Coastguard Worker   return true;
532*795d594fSAndroid Build Coastguard Worker }
533*795d594fSAndroid Build Coastguard Worker 
SetVRegPair(ArtMethod * m,uint16_t vreg,uint64_t new_value,VRegKind kind_lo,VRegKind kind_hi)534*795d594fSAndroid Build Coastguard Worker bool StackVisitor::SetVRegPair(ArtMethod* m,
535*795d594fSAndroid Build Coastguard Worker                                uint16_t vreg,
536*795d594fSAndroid Build Coastguard Worker                                uint64_t new_value,
537*795d594fSAndroid Build Coastguard Worker                                VRegKind kind_lo,
538*795d594fSAndroid Build Coastguard Worker                                VRegKind kind_hi) {
539*795d594fSAndroid Build Coastguard Worker   if (kind_lo == kLongLoVReg) {
540*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(kind_hi, kLongHiVReg);
541*795d594fSAndroid Build Coastguard Worker   } else if (kind_lo == kDoubleLoVReg) {
542*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(kind_hi, kDoubleHiVReg);
543*795d594fSAndroid Build Coastguard Worker   } else {
544*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Expected long or double: kind_lo=" << kind_lo << ", kind_hi=" << kind_hi;
545*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
546*795d594fSAndroid Build Coastguard Worker   }
547*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ true);
548*795d594fSAndroid Build Coastguard Worker   if (shadow_frame == nullptr) {
549*795d594fSAndroid Build Coastguard Worker     return false;
550*795d594fSAndroid Build Coastguard Worker   }
551*795d594fSAndroid Build Coastguard Worker   shadow_frame->SetVRegLong(vreg, new_value);
552*795d594fSAndroid Build Coastguard Worker   return true;
553*795d594fSAndroid Build Coastguard Worker }
554*795d594fSAndroid Build Coastguard Worker 
IsAccessibleGPR(uint32_t reg) const555*795d594fSAndroid Build Coastguard Worker bool StackVisitor::IsAccessibleGPR(uint32_t reg) const {
556*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);
557*795d594fSAndroid Build Coastguard Worker   return context_->IsAccessibleGPR(reg);
558*795d594fSAndroid Build Coastguard Worker }
559*795d594fSAndroid Build Coastguard Worker 
GetGPRAddress(uint32_t reg) const560*795d594fSAndroid Build Coastguard Worker uintptr_t* StackVisitor::GetGPRAddress(uint32_t reg) const {
561*795d594fSAndroid Build Coastguard Worker   DCHECK(cur_quick_frame_ != nullptr) << "This is a quick frame routine";
562*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);
563*795d594fSAndroid Build Coastguard Worker   return context_->GetGPRAddress(reg);
564*795d594fSAndroid Build Coastguard Worker }
565*795d594fSAndroid Build Coastguard Worker 
GetGPR(uint32_t reg) const566*795d594fSAndroid Build Coastguard Worker uintptr_t StackVisitor::GetGPR(uint32_t reg) const {
567*795d594fSAndroid Build Coastguard Worker   DCHECK(cur_quick_frame_ != nullptr) << "This is a quick frame routine";
568*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);
569*795d594fSAndroid Build Coastguard Worker   return context_->GetGPR(reg);
570*795d594fSAndroid Build Coastguard Worker }
571*795d594fSAndroid Build Coastguard Worker 
IsAccessibleFPR(uint32_t reg) const572*795d594fSAndroid Build Coastguard Worker bool StackVisitor::IsAccessibleFPR(uint32_t reg) const {
573*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);
574*795d594fSAndroid Build Coastguard Worker   return context_->IsAccessibleFPR(reg);
575*795d594fSAndroid Build Coastguard Worker }
576*795d594fSAndroid Build Coastguard Worker 
GetFPR(uint32_t reg) const577*795d594fSAndroid Build Coastguard Worker uintptr_t StackVisitor::GetFPR(uint32_t reg) const {
578*795d594fSAndroid Build Coastguard Worker   DCHECK(cur_quick_frame_ != nullptr) << "This is a quick frame routine";
579*795d594fSAndroid Build Coastguard Worker   DCHECK(context_ != nullptr);
580*795d594fSAndroid Build Coastguard Worker   return context_->GetFPR(reg);
581*795d594fSAndroid Build Coastguard Worker }
582*795d594fSAndroid Build Coastguard Worker 
GetReturnPcAddr() const583*795d594fSAndroid Build Coastguard Worker uintptr_t StackVisitor::GetReturnPcAddr() const {
584*795d594fSAndroid Build Coastguard Worker   uintptr_t sp = reinterpret_cast<uintptr_t>(GetCurrentQuickFrame());
585*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(sp, 0u);
586*795d594fSAndroid Build Coastguard Worker   return sp + GetCurrentQuickFrameInfo().GetReturnPcOffset();
587*795d594fSAndroid Build Coastguard Worker }
588*795d594fSAndroid Build Coastguard Worker 
GetReturnPc() const589*795d594fSAndroid Build Coastguard Worker uintptr_t StackVisitor::GetReturnPc() const {
590*795d594fSAndroid Build Coastguard Worker   return *reinterpret_cast<uintptr_t*>(GetReturnPcAddr());
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker 
SetReturnPc(uintptr_t new_ret_pc)593*795d594fSAndroid Build Coastguard Worker void StackVisitor::SetReturnPc(uintptr_t new_ret_pc) {
594*795d594fSAndroid Build Coastguard Worker   *reinterpret_cast<uintptr_t*>(GetReturnPcAddr()) = new_ret_pc;
595*795d594fSAndroid Build Coastguard Worker }
596*795d594fSAndroid Build Coastguard Worker 
ComputeNumFrames(Thread * thread,StackWalkKind walk_kind)597*795d594fSAndroid Build Coastguard Worker size_t StackVisitor::ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) {
598*795d594fSAndroid Build Coastguard Worker   struct NumFramesVisitor : public StackVisitor {
599*795d594fSAndroid Build Coastguard Worker     NumFramesVisitor(Thread* thread_in, StackWalkKind walk_kind_in)
600*795d594fSAndroid Build Coastguard Worker         : StackVisitor(thread_in, nullptr, walk_kind_in), frames(0) {}
601*795d594fSAndroid Build Coastguard Worker 
602*795d594fSAndroid Build Coastguard Worker     bool VisitFrame() override {
603*795d594fSAndroid Build Coastguard Worker       frames++;
604*795d594fSAndroid Build Coastguard Worker       return true;
605*795d594fSAndroid Build Coastguard Worker     }
606*795d594fSAndroid Build Coastguard Worker 
607*795d594fSAndroid Build Coastguard Worker     size_t frames;
608*795d594fSAndroid Build Coastguard Worker   };
609*795d594fSAndroid Build Coastguard Worker   NumFramesVisitor visitor(thread, walk_kind);
610*795d594fSAndroid Build Coastguard Worker   visitor.WalkStack(true);
611*795d594fSAndroid Build Coastguard Worker   return visitor.frames;
612*795d594fSAndroid Build Coastguard Worker }
613*795d594fSAndroid Build Coastguard Worker 
GetNextMethodAndDexPc(ArtMethod ** next_method,uint32_t * next_dex_pc)614*795d594fSAndroid Build Coastguard Worker bool StackVisitor::GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc) {
615*795d594fSAndroid Build Coastguard Worker   struct HasMoreFramesVisitor : public StackVisitor {
616*795d594fSAndroid Build Coastguard Worker     HasMoreFramesVisitor(Thread* thread,
617*795d594fSAndroid Build Coastguard Worker                          StackWalkKind walk_kind,
618*795d594fSAndroid Build Coastguard Worker                          size_t num_frames,
619*795d594fSAndroid Build Coastguard Worker                          size_t frame_height)
620*795d594fSAndroid Build Coastguard Worker         : StackVisitor(thread, nullptr, walk_kind, num_frames),
621*795d594fSAndroid Build Coastguard Worker           frame_height_(frame_height),
622*795d594fSAndroid Build Coastguard Worker           found_frame_(false),
623*795d594fSAndroid Build Coastguard Worker           has_more_frames_(false),
624*795d594fSAndroid Build Coastguard Worker           next_method_(nullptr),
625*795d594fSAndroid Build Coastguard Worker           next_dex_pc_(0) {
626*795d594fSAndroid Build Coastguard Worker     }
627*795d594fSAndroid Build Coastguard Worker 
628*795d594fSAndroid Build Coastguard Worker     bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
629*795d594fSAndroid Build Coastguard Worker       if (found_frame_) {
630*795d594fSAndroid Build Coastguard Worker         ArtMethod* method = GetMethod();
631*795d594fSAndroid Build Coastguard Worker         if (method != nullptr && !method->IsRuntimeMethod()) {
632*795d594fSAndroid Build Coastguard Worker           has_more_frames_ = true;
633*795d594fSAndroid Build Coastguard Worker           next_method_ = method;
634*795d594fSAndroid Build Coastguard Worker           next_dex_pc_ = GetDexPc();
635*795d594fSAndroid Build Coastguard Worker           return false;  // End stack walk once next method is found.
636*795d594fSAndroid Build Coastguard Worker         }
637*795d594fSAndroid Build Coastguard Worker       } else if (GetFrameHeight() == frame_height_) {
638*795d594fSAndroid Build Coastguard Worker         found_frame_ = true;
639*795d594fSAndroid Build Coastguard Worker       }
640*795d594fSAndroid Build Coastguard Worker       return true;
641*795d594fSAndroid Build Coastguard Worker     }
642*795d594fSAndroid Build Coastguard Worker 
643*795d594fSAndroid Build Coastguard Worker     size_t frame_height_;
644*795d594fSAndroid Build Coastguard Worker     bool found_frame_;
645*795d594fSAndroid Build Coastguard Worker     bool has_more_frames_;
646*795d594fSAndroid Build Coastguard Worker     ArtMethod* next_method_;
647*795d594fSAndroid Build Coastguard Worker     uint32_t next_dex_pc_;
648*795d594fSAndroid Build Coastguard Worker   };
649*795d594fSAndroid Build Coastguard Worker   HasMoreFramesVisitor visitor(thread_, walk_kind_, GetNumFrames(), GetFrameHeight());
650*795d594fSAndroid Build Coastguard Worker   visitor.WalkStack(true);
651*795d594fSAndroid Build Coastguard Worker   *next_method = visitor.next_method_;
652*795d594fSAndroid Build Coastguard Worker   *next_dex_pc = visitor.next_dex_pc_;
653*795d594fSAndroid Build Coastguard Worker   return visitor.has_more_frames_;
654*795d594fSAndroid Build Coastguard Worker }
655*795d594fSAndroid Build Coastguard Worker 
DescribeStack(Thread * thread)656*795d594fSAndroid Build Coastguard Worker void StackVisitor::DescribeStack(Thread* thread) {
657*795d594fSAndroid Build Coastguard Worker   struct DescribeStackVisitor : public StackVisitor {
658*795d594fSAndroid Build Coastguard Worker     explicit DescribeStackVisitor(Thread* thread_in)
659*795d594fSAndroid Build Coastguard Worker         : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
660*795d594fSAndroid Build Coastguard Worker 
661*795d594fSAndroid Build Coastguard Worker     bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
662*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Frame Id=" << GetFrameId() << " " << DescribeLocation();
663*795d594fSAndroid Build Coastguard Worker       return true;
664*795d594fSAndroid Build Coastguard Worker     }
665*795d594fSAndroid Build Coastguard Worker   };
666*795d594fSAndroid Build Coastguard Worker   DescribeStackVisitor visitor(thread);
667*795d594fSAndroid Build Coastguard Worker   visitor.WalkStack(true);
668*795d594fSAndroid Build Coastguard Worker }
669*795d594fSAndroid Build Coastguard Worker 
DescribeLocation() const670*795d594fSAndroid Build Coastguard Worker std::string StackVisitor::DescribeLocation() const {
671*795d594fSAndroid Build Coastguard Worker   std::string result("Visiting method '");
672*795d594fSAndroid Build Coastguard Worker   ArtMethod* m = GetMethod();
673*795d594fSAndroid Build Coastguard Worker   if (m == nullptr) {
674*795d594fSAndroid Build Coastguard Worker     return "upcall";
675*795d594fSAndroid Build Coastguard Worker   }
676*795d594fSAndroid Build Coastguard Worker   result += m->PrettyMethod();
677*795d594fSAndroid Build Coastguard Worker   result += StringPrintf("' at dex PC 0x%04x", GetDexPc());
678*795d594fSAndroid Build Coastguard Worker   if (!IsShadowFrame()) {
679*795d594fSAndroid Build Coastguard Worker     result += StringPrintf(" (native PC %p)", reinterpret_cast<void*>(GetCurrentQuickFramePc()));
680*795d594fSAndroid Build Coastguard Worker   }
681*795d594fSAndroid Build Coastguard Worker   return result;
682*795d594fSAndroid Build Coastguard Worker }
683*795d594fSAndroid Build Coastguard Worker 
SetMethod(ArtMethod * method)684*795d594fSAndroid Build Coastguard Worker void StackVisitor::SetMethod(ArtMethod* method) {
685*795d594fSAndroid Build Coastguard Worker   DCHECK(GetMethod() != nullptr);
686*795d594fSAndroid Build Coastguard Worker   if (cur_shadow_frame_ != nullptr) {
687*795d594fSAndroid Build Coastguard Worker     cur_shadow_frame_->SetMethod(method);
688*795d594fSAndroid Build Coastguard Worker   } else {
689*795d594fSAndroid Build Coastguard Worker     DCHECK(cur_quick_frame_ != nullptr);
690*795d594fSAndroid Build Coastguard Worker     CHECK(!IsInInlinedFrame()) << "We do not support setting inlined method's ArtMethod: "
691*795d594fSAndroid Build Coastguard Worker                                << GetMethod()->PrettyMethod() << " is inlined into "
692*795d594fSAndroid Build Coastguard Worker                                << GetOuterMethod()->PrettyMethod();
693*795d594fSAndroid Build Coastguard Worker     *cur_quick_frame_ = method;
694*795d594fSAndroid Build Coastguard Worker   }
695*795d594fSAndroid Build Coastguard Worker }
696*795d594fSAndroid Build Coastguard Worker 
ValidateFrame() const697*795d594fSAndroid Build Coastguard Worker void StackVisitor::ValidateFrame() const {
698*795d594fSAndroid Build Coastguard Worker   if (!kIsDebugBuild) {
699*795d594fSAndroid Build Coastguard Worker     return;
700*795d594fSAndroid Build Coastguard Worker   }
701*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = GetMethod();
702*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
703*795d594fSAndroid Build Coastguard Worker   // Runtime methods have null declaring class.
704*795d594fSAndroid Build Coastguard Worker   if (!method->IsRuntimeMethod()) {
705*795d594fSAndroid Build Coastguard Worker     CHECK(declaring_class != nullptr);
706*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(declaring_class->GetClass(), declaring_class->GetClass()->GetClass())
707*795d594fSAndroid Build Coastguard Worker         << declaring_class;
708*795d594fSAndroid Build Coastguard Worker   } else {
709*795d594fSAndroid Build Coastguard Worker     CHECK(declaring_class == nullptr);
710*795d594fSAndroid Build Coastguard Worker   }
711*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
712*795d594fSAndroid Build Coastguard Worker   LinearAlloc* const linear_alloc = runtime->GetLinearAlloc();
713*795d594fSAndroid Build Coastguard Worker   if (!linear_alloc->Contains(method)) {
714*795d594fSAndroid Build Coastguard Worker     // Check class linker linear allocs.
715*795d594fSAndroid Build Coastguard Worker     // We get the canonical method as copied methods may have been allocated
716*795d594fSAndroid Build Coastguard Worker     // by a different class loader.
717*795d594fSAndroid Build Coastguard Worker     const PointerSize ptrSize = runtime->GetClassLinker()->GetImagePointerSize();
718*795d594fSAndroid Build Coastguard Worker     ArtMethod* canonical = method->GetCanonicalMethod(ptrSize);
719*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> klass = canonical->GetDeclaringClass();
720*795d594fSAndroid Build Coastguard Worker     LinearAlloc* const class_linear_alloc = (klass != nullptr)
721*795d594fSAndroid Build Coastguard Worker         ? runtime->GetClassLinker()->GetAllocatorForClassLoader(klass->GetClassLoader())
722*795d594fSAndroid Build Coastguard Worker         : linear_alloc;
723*795d594fSAndroid Build Coastguard Worker     if (!class_linear_alloc->Contains(canonical)) {
724*795d594fSAndroid Build Coastguard Worker       // Check image space.
725*795d594fSAndroid Build Coastguard Worker       bool in_image = false;
726*795d594fSAndroid Build Coastguard Worker       for (auto& space : runtime->GetHeap()->GetContinuousSpaces()) {
727*795d594fSAndroid Build Coastguard Worker         if (space->IsImageSpace()) {
728*795d594fSAndroid Build Coastguard Worker           auto* image_space = space->AsImageSpace();
729*795d594fSAndroid Build Coastguard Worker           const auto& header = image_space->GetImageHeader();
730*795d594fSAndroid Build Coastguard Worker           const ImageSection& methods = header.GetMethodsSection();
731*795d594fSAndroid Build Coastguard Worker           const ImageSection& runtime_methods = header.GetRuntimeMethodsSection();
732*795d594fSAndroid Build Coastguard Worker           const size_t offset =  reinterpret_cast<const uint8_t*>(canonical) - image_space->Begin();
733*795d594fSAndroid Build Coastguard Worker           if (methods.Contains(offset) || runtime_methods.Contains(offset)) {
734*795d594fSAndroid Build Coastguard Worker             in_image = true;
735*795d594fSAndroid Build Coastguard Worker             break;
736*795d594fSAndroid Build Coastguard Worker           }
737*795d594fSAndroid Build Coastguard Worker         }
738*795d594fSAndroid Build Coastguard Worker       }
739*795d594fSAndroid Build Coastguard Worker       CHECK(in_image) << canonical->PrettyMethod() << " not in linear alloc or image";
740*795d594fSAndroid Build Coastguard Worker     }
741*795d594fSAndroid Build Coastguard Worker   }
742*795d594fSAndroid Build Coastguard Worker   if (cur_quick_frame_ != nullptr) {
743*795d594fSAndroid Build Coastguard Worker     // Frame consistency checks.
744*795d594fSAndroid Build Coastguard Worker     size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
745*795d594fSAndroid Build Coastguard Worker     CHECK_NE(frame_size, 0u);
746*795d594fSAndroid Build Coastguard Worker     // For compiled code, we could try to have a rough guess at an upper size we expect
747*795d594fSAndroid Build Coastguard Worker     // to see for a frame:
748*795d594fSAndroid Build Coastguard Worker     // 256 registers
749*795d594fSAndroid Build Coastguard Worker     // 2 words HandleScope overhead
750*795d594fSAndroid Build Coastguard Worker     // 3+3 register spills
751*795d594fSAndroid Build Coastguard Worker     // const size_t kMaxExpectedFrameSize = (256 + 2 + 3 + 3) * sizeof(word);
752*795d594fSAndroid Build Coastguard Worker     const size_t kMaxExpectedFrameSize = interpreter::kNterpMaxFrame;
753*795d594fSAndroid Build Coastguard Worker     CHECK_LE(frame_size, kMaxExpectedFrameSize) << method->PrettyMethod();
754*795d594fSAndroid Build Coastguard Worker     size_t return_pc_offset = GetCurrentQuickFrameInfo().GetReturnPcOffset();
755*795d594fSAndroid Build Coastguard Worker     CHECK_LT(return_pc_offset, frame_size);
756*795d594fSAndroid Build Coastguard Worker   }
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker 
GetCurrentQuickFrameInfo() const759*795d594fSAndroid Build Coastguard Worker QuickMethodFrameInfo StackVisitor::GetCurrentQuickFrameInfo() const {
760*795d594fSAndroid Build Coastguard Worker   if (cur_oat_quick_method_header_ != nullptr) {
761*795d594fSAndroid Build Coastguard Worker     if (cur_oat_quick_method_header_->IsOptimized()) {
762*795d594fSAndroid Build Coastguard Worker       return cur_oat_quick_method_header_->GetFrameInfo();
763*795d594fSAndroid Build Coastguard Worker     } else {
764*795d594fSAndroid Build Coastguard Worker       DCHECK(cur_oat_quick_method_header_->IsNterpMethodHeader());
765*795d594fSAndroid Build Coastguard Worker       return NterpFrameInfo(cur_quick_frame_);
766*795d594fSAndroid Build Coastguard Worker     }
767*795d594fSAndroid Build Coastguard Worker   }
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = GetMethod();
770*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
771*795d594fSAndroid Build Coastguard Worker 
772*795d594fSAndroid Build Coastguard Worker   if (method->IsAbstract()) {
773*795d594fSAndroid Build Coastguard Worker     return RuntimeCalleeSaveFrame::GetMethodFrameInfo(CalleeSaveType::kSaveRefsAndArgs);
774*795d594fSAndroid Build Coastguard Worker   }
775*795d594fSAndroid Build Coastguard Worker 
776*795d594fSAndroid Build Coastguard Worker   // This goes before IsProxyMethod since runtime methods have a null declaring class.
777*795d594fSAndroid Build Coastguard Worker   if (method->IsRuntimeMethod()) {
778*795d594fSAndroid Build Coastguard Worker     return runtime->GetRuntimeMethodFrameInfo(method);
779*795d594fSAndroid Build Coastguard Worker   }
780*795d594fSAndroid Build Coastguard Worker 
781*795d594fSAndroid Build Coastguard Worker   if (method->IsProxyMethod()) {
782*795d594fSAndroid Build Coastguard Worker     // There is only one direct method of a proxy class: the constructor. A direct method is
783*795d594fSAndroid Build Coastguard Worker     // cloned from the original java.lang.reflect.Proxy and is executed as usual quick
784*795d594fSAndroid Build Coastguard Worker     // compiled method without any stubs. Therefore the method must have a OatQuickMethodHeader.
785*795d594fSAndroid Build Coastguard Worker     DCHECK(!method->IsDirect() && !method->IsConstructor())
786*795d594fSAndroid Build Coastguard Worker         << "Constructors of proxy classes must have a OatQuickMethodHeader";
787*795d594fSAndroid Build Coastguard Worker     return RuntimeCalleeSaveFrame::GetMethodFrameInfo(CalleeSaveType::kSaveRefsAndArgs);
788*795d594fSAndroid Build Coastguard Worker   }
789*795d594fSAndroid Build Coastguard Worker 
790*795d594fSAndroid Build Coastguard Worker   // The only remaining cases are for native methods that either
791*795d594fSAndroid Build Coastguard Worker   //   - use the Generic JNI stub, called either directly or through some
792*795d594fSAndroid Build Coastguard Worker   //     (resolution, instrumentation) trampoline; or
793*795d594fSAndroid Build Coastguard Worker   //   - fake a Generic JNI frame in art_jni_dlsym_lookup_critical_stub.
794*795d594fSAndroid Build Coastguard Worker   DCHECK(method->IsNative());
795*795d594fSAndroid Build Coastguard Worker   // Generic JNI frame is just like the SaveRefsAndArgs frame.
796*795d594fSAndroid Build Coastguard Worker   // Note that HandleScope, if any, is below the frame.
797*795d594fSAndroid Build Coastguard Worker   return RuntimeCalleeSaveFrame::GetMethodFrameInfo(CalleeSaveType::kSaveRefsAndArgs);
798*795d594fSAndroid Build Coastguard Worker }
799*795d594fSAndroid Build Coastguard Worker 
GetShouldDeoptimizeFlagAddr() const800*795d594fSAndroid Build Coastguard Worker uint8_t* StackVisitor::GetShouldDeoptimizeFlagAddr() const REQUIRES_SHARED(Locks::mutator_lock_) {
801*795d594fSAndroid Build Coastguard Worker   DCHECK(GetCurrentOatQuickMethodHeader()->HasShouldDeoptimizeFlag());
802*795d594fSAndroid Build Coastguard Worker   QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
803*795d594fSAndroid Build Coastguard Worker   size_t frame_size = frame_info.FrameSizeInBytes();
804*795d594fSAndroid Build Coastguard Worker   uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
805*795d594fSAndroid Build Coastguard Worker   size_t core_spill_size =
806*795d594fSAndroid Build Coastguard Worker       POPCOUNT(frame_info.CoreSpillMask()) * GetBytesPerGprSpillLocation(kRuntimeQuickCodeISA);
807*795d594fSAndroid Build Coastguard Worker   size_t fpu_spill_size =
808*795d594fSAndroid Build Coastguard Worker       POPCOUNT(frame_info.FpSpillMask()) * GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA);
809*795d594fSAndroid Build Coastguard Worker   size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
810*795d594fSAndroid Build Coastguard Worker   uint8_t* should_deoptimize_addr = sp + offset;
811*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(*should_deoptimize_addr & ~static_cast<uint8_t>(DeoptimizeFlagValue::kAll), 0);
812*795d594fSAndroid Build Coastguard Worker   return should_deoptimize_addr;
813*795d594fSAndroid Build Coastguard Worker }
814*795d594fSAndroid Build Coastguard Worker 
815*795d594fSAndroid Build Coastguard Worker template <StackVisitor::CountTransitions kCount>
WalkStack(bool include_transitions)816*795d594fSAndroid Build Coastguard Worker void StackVisitor::WalkStack(bool include_transitions) {
817*795d594fSAndroid Build Coastguard Worker   if (check_suspended_) {
818*795d594fSAndroid Build Coastguard Worker     DCHECK(thread_ == Thread::Current() || thread_->GetState() != ThreadState::kRunnable);
819*795d594fSAndroid Build Coastguard Worker   }
820*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(cur_depth_, 0U);
821*795d594fSAndroid Build Coastguard Worker 
822*795d594fSAndroid Build Coastguard Worker   for (const ManagedStack* current_fragment = thread_->GetManagedStack();
823*795d594fSAndroid Build Coastguard Worker        current_fragment != nullptr; current_fragment = current_fragment->GetLink()) {
824*795d594fSAndroid Build Coastguard Worker     cur_shadow_frame_ = current_fragment->GetTopShadowFrame();
825*795d594fSAndroid Build Coastguard Worker     cur_quick_frame_ = current_fragment->GetTopQuickFrame();
826*795d594fSAndroid Build Coastguard Worker     cur_quick_frame_pc_ = 0;
827*795d594fSAndroid Build Coastguard Worker     DCHECK(cur_oat_quick_method_header_ == nullptr);
828*795d594fSAndroid Build Coastguard Worker 
829*795d594fSAndroid Build Coastguard Worker     if (kDebugStackWalk) {
830*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Tid=" << thread_-> GetThreadId()
831*795d594fSAndroid Build Coastguard Worker           << ", ManagedStack fragement: " << current_fragment;
832*795d594fSAndroid Build Coastguard Worker     }
833*795d594fSAndroid Build Coastguard Worker 
834*795d594fSAndroid Build Coastguard Worker     if (cur_quick_frame_ != nullptr) {  // Handle quick stack frames.
835*795d594fSAndroid Build Coastguard Worker       // Can't be both a shadow and a quick fragment.
836*795d594fSAndroid Build Coastguard Worker       DCHECK(current_fragment->GetTopShadowFrame() == nullptr);
837*795d594fSAndroid Build Coastguard Worker       ArtMethod* method = *cur_quick_frame_;
838*795d594fSAndroid Build Coastguard Worker       DCHECK(method != nullptr);
839*795d594fSAndroid Build Coastguard Worker       bool header_retrieved = false;
840*795d594fSAndroid Build Coastguard Worker       if (method->IsNative()) {
841*795d594fSAndroid Build Coastguard Worker         // We do not have a PC for the first frame, so we cannot simply use
842*795d594fSAndroid Build Coastguard Worker         // ArtMethod::GetOatQuickMethodHeader() as we're unable to distinguish there
843*795d594fSAndroid Build Coastguard Worker         // between GenericJNI frame and JIT-compiled JNI stub; the entrypoint may have
844*795d594fSAndroid Build Coastguard Worker         // changed since the frame was entered. The top quick frame tag indicates
845*795d594fSAndroid Build Coastguard Worker         // GenericJNI here, otherwise it's either AOT-compiled or JNI-compiled JNI stub.
846*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(current_fragment->GetTopQuickFrameGenericJniTag())) {
847*795d594fSAndroid Build Coastguard Worker           // The generic JNI does not have any method header.
848*795d594fSAndroid Build Coastguard Worker           cur_oat_quick_method_header_ = nullptr;
849*795d594fSAndroid Build Coastguard Worker         } else if (UNLIKELY(current_fragment->GetTopQuickFrameJitJniTag())) {
850*795d594fSAndroid Build Coastguard Worker           // Should be JITed code.
851*795d594fSAndroid Build Coastguard Worker           Runtime* runtime = Runtime::Current();
852*795d594fSAndroid Build Coastguard Worker           const void* code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method);
853*795d594fSAndroid Build Coastguard Worker           CHECK(code != nullptr) << method->PrettyMethod();
854*795d594fSAndroid Build Coastguard Worker           cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code);
855*795d594fSAndroid Build Coastguard Worker         } else {
856*795d594fSAndroid Build Coastguard Worker           // We are sure we are not running GenericJni here. Though the entry point could still be
857*795d594fSAndroid Build Coastguard Worker           // GenericJnistub. The entry point is usually JITed or AOT code. It could be also a
858*795d594fSAndroid Build Coastguard Worker           // resolution stub if the class isn't visibly initialized yet.
859*795d594fSAndroid Build Coastguard Worker           const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode();
860*795d594fSAndroid Build Coastguard Worker           CHECK(existing_entry_point != nullptr);
861*795d594fSAndroid Build Coastguard Worker           Runtime* runtime = Runtime::Current();
862*795d594fSAndroid Build Coastguard Worker           ClassLinker* class_linker = runtime->GetClassLinker();
863*795d594fSAndroid Build Coastguard Worker           // Check whether we can quickly get the header from the current entrypoint.
864*795d594fSAndroid Build Coastguard Worker           if (!class_linker->IsQuickGenericJniStub(existing_entry_point) &&
865*795d594fSAndroid Build Coastguard Worker               !class_linker->IsQuickResolutionStub(existing_entry_point)) {
866*795d594fSAndroid Build Coastguard Worker             cur_oat_quick_method_header_ =
867*795d594fSAndroid Build Coastguard Worker                 OatQuickMethodHeader::FromEntryPoint(existing_entry_point);
868*795d594fSAndroid Build Coastguard Worker           } else {
869*795d594fSAndroid Build Coastguard Worker             const void* code = method->GetOatMethodQuickCode(class_linker->GetImagePointerSize());
870*795d594fSAndroid Build Coastguard Worker             if (code != nullptr) {
871*795d594fSAndroid Build Coastguard Worker               cur_oat_quick_method_header_ = OatQuickMethodHeader::FromEntryPoint(code);
872*795d594fSAndroid Build Coastguard Worker             } else {
873*795d594fSAndroid Build Coastguard Worker               // For non-debuggable runtimes, the JNI stub can be JIT-compiled or AOT-compiled, and
874*795d594fSAndroid Build Coastguard Worker               // can also reuse the stub in boot images. Since we checked for AOT code earlier, we
875*795d594fSAndroid Build Coastguard Worker               // must be running JITed code or boot JNI stub.
876*795d594fSAndroid Build Coastguard Worker               // For debuggable runtimes, we won't be here as we never use AOT code in debuggable.
877*795d594fSAndroid Build Coastguard Worker               // And the JIT situation is handled earlier as its SP will be tagged. But there is a
878*795d594fSAndroid Build Coastguard Worker               // special case where we change runtime state from non-debuggable to debuggable in
879*795d594fSAndroid Build Coastguard Worker               // the JNI implementation and do deopt inside, which could be treated as
880*795d594fSAndroid Build Coastguard Worker               // a case of non-debuggable as well.
881*795d594fSAndroid Build Coastguard Worker               if (runtime->GetJit() != nullptr) {
882*795d594fSAndroid Build Coastguard Worker                 code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method);
883*795d594fSAndroid Build Coastguard Worker               }
884*795d594fSAndroid Build Coastguard Worker               if (code == nullptr) {
885*795d594fSAndroid Build Coastguard Worker                 // Check if current method uses the boot JNI stub.
886*795d594fSAndroid Build Coastguard Worker                 const void* boot_jni_stub = class_linker->FindBootJniStub(method);
887*795d594fSAndroid Build Coastguard Worker                 if (boot_jni_stub != nullptr) {
888*795d594fSAndroid Build Coastguard Worker                   code = EntryPointToCodePointer(boot_jni_stub);
889*795d594fSAndroid Build Coastguard Worker                 }
890*795d594fSAndroid Build Coastguard Worker               }
891*795d594fSAndroid Build Coastguard Worker               CHECK(code != nullptr) << method->PrettyMethod();
892*795d594fSAndroid Build Coastguard Worker               cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code);
893*795d594fSAndroid Build Coastguard Worker             }
894*795d594fSAndroid Build Coastguard Worker           }
895*795d594fSAndroid Build Coastguard Worker         }
896*795d594fSAndroid Build Coastguard Worker         header_retrieved = true;
897*795d594fSAndroid Build Coastguard Worker       }
898*795d594fSAndroid Build Coastguard Worker       while (method != nullptr) {
899*795d594fSAndroid Build Coastguard Worker         if (!header_retrieved) {
900*795d594fSAndroid Build Coastguard Worker           cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_);
901*795d594fSAndroid Build Coastguard Worker         }
902*795d594fSAndroid Build Coastguard Worker         header_retrieved = false;  // Force header retrieval in next iteration.
903*795d594fSAndroid Build Coastguard Worker 
904*795d594fSAndroid Build Coastguard Worker         if (kDebugStackWalk) {
905*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "Early print: Tid=" << thread_-> GetThreadId() << ", method: "
906*795d594fSAndroid Build Coastguard Worker               << ArtMethod::PrettyMethod(method) << "@" << method;
907*795d594fSAndroid Build Coastguard Worker         }
908*795d594fSAndroid Build Coastguard Worker         ValidateFrame();
909*795d594fSAndroid Build Coastguard Worker         if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
910*795d594fSAndroid Build Coastguard Worker             && (cur_oat_quick_method_header_ != nullptr)
911*795d594fSAndroid Build Coastguard Worker             && cur_oat_quick_method_header_->IsOptimized()
912*795d594fSAndroid Build Coastguard Worker             && !method->IsNative()  // JNI methods cannot have any inlined frames.
913*795d594fSAndroid Build Coastguard Worker             && CodeInfo::HasInlineInfo(cur_oat_quick_method_header_->GetOptimizedCodeInfoPtr())) {
914*795d594fSAndroid Build Coastguard Worker           DCHECK_NE(cur_quick_frame_pc_, 0u);
915*795d594fSAndroid Build Coastguard Worker           CodeInfo* code_info = GetCurrentInlineInfo();
916*795d594fSAndroid Build Coastguard Worker           StackMap* stack_map = GetCurrentStackMap();
917*795d594fSAndroid Build Coastguard Worker           if (stack_map->IsValid() && stack_map->HasInlineInfo()) {
918*795d594fSAndroid Build Coastguard Worker             DCHECK_EQ(current_inline_frames_.size(), 0u);
919*795d594fSAndroid Build Coastguard Worker             for (current_inline_frames_ = code_info->GetInlineInfosOf(*stack_map);
920*795d594fSAndroid Build Coastguard Worker                  !current_inline_frames_.empty();
921*795d594fSAndroid Build Coastguard Worker                  current_inline_frames_.pop_back()) {
922*795d594fSAndroid Build Coastguard Worker               bool should_continue = VisitFrame();
923*795d594fSAndroid Build Coastguard Worker               if (UNLIKELY(!should_continue)) {
924*795d594fSAndroid Build Coastguard Worker                 return;
925*795d594fSAndroid Build Coastguard Worker               }
926*795d594fSAndroid Build Coastguard Worker               cur_depth_++;
927*795d594fSAndroid Build Coastguard Worker             }
928*795d594fSAndroid Build Coastguard Worker           }
929*795d594fSAndroid Build Coastguard Worker         }
930*795d594fSAndroid Build Coastguard Worker 
931*795d594fSAndroid Build Coastguard Worker         bool should_continue = VisitFrame();
932*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(!should_continue)) {
933*795d594fSAndroid Build Coastguard Worker           return;
934*795d594fSAndroid Build Coastguard Worker         }
935*795d594fSAndroid Build Coastguard Worker 
936*795d594fSAndroid Build Coastguard Worker         QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
937*795d594fSAndroid Build Coastguard Worker         if (context_ != nullptr) {
938*795d594fSAndroid Build Coastguard Worker           context_->FillCalleeSaves(reinterpret_cast<uint8_t*>(cur_quick_frame_), frame_info);
939*795d594fSAndroid Build Coastguard Worker         }
940*795d594fSAndroid Build Coastguard Worker         // Compute PC for next stack frame from return PC.
941*795d594fSAndroid Build Coastguard Worker         size_t frame_size = frame_info.FrameSizeInBytes();
942*795d594fSAndroid Build Coastguard Worker         uintptr_t return_pc_addr = GetReturnPcAddr();
943*795d594fSAndroid Build Coastguard Worker 
944*795d594fSAndroid Build Coastguard Worker         cur_quick_frame_pc_ = *reinterpret_cast<uintptr_t*>(return_pc_addr);
945*795d594fSAndroid Build Coastguard Worker         uint8_t* next_frame = reinterpret_cast<uint8_t*>(cur_quick_frame_) + frame_size;
946*795d594fSAndroid Build Coastguard Worker         cur_quick_frame_ = reinterpret_cast<ArtMethod**>(next_frame);
947*795d594fSAndroid Build Coastguard Worker 
948*795d594fSAndroid Build Coastguard Worker         if (kDebugStackWalk) {
949*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "Tid=" << thread_-> GetThreadId() << ", method: "
950*795d594fSAndroid Build Coastguard Worker               << ArtMethod::PrettyMethod(method) << "@" << method << " size=" << frame_size
951*795d594fSAndroid Build Coastguard Worker               << std::boolalpha
952*795d594fSAndroid Build Coastguard Worker               << " optimized=" << (cur_oat_quick_method_header_ != nullptr &&
953*795d594fSAndroid Build Coastguard Worker                                    cur_oat_quick_method_header_->IsOptimized())
954*795d594fSAndroid Build Coastguard Worker               << " native=" << method->IsNative()
955*795d594fSAndroid Build Coastguard Worker               << std::noboolalpha
956*795d594fSAndroid Build Coastguard Worker               << " entrypoints=" << method->GetEntryPointFromQuickCompiledCode()
957*795d594fSAndroid Build Coastguard Worker               << "," << (method->IsNative() ? method->GetEntryPointFromJni() : nullptr)
958*795d594fSAndroid Build Coastguard Worker               << " next=" << *cur_quick_frame_;
959*795d594fSAndroid Build Coastguard Worker         }
960*795d594fSAndroid Build Coastguard Worker 
961*795d594fSAndroid Build Coastguard Worker         if (kCount == CountTransitions::kYes || !method->IsRuntimeMethod()) {
962*795d594fSAndroid Build Coastguard Worker           cur_depth_++;
963*795d594fSAndroid Build Coastguard Worker         }
964*795d594fSAndroid Build Coastguard Worker         method = *cur_quick_frame_;
965*795d594fSAndroid Build Coastguard Worker       }
966*795d594fSAndroid Build Coastguard Worker       // We reached a transition frame, it doesn't have a method header.
967*795d594fSAndroid Build Coastguard Worker       cur_oat_quick_method_header_ = nullptr;
968*795d594fSAndroid Build Coastguard Worker     } else if (cur_shadow_frame_ != nullptr) {
969*795d594fSAndroid Build Coastguard Worker       do {
970*795d594fSAndroid Build Coastguard Worker         if (kDebugStackWalk) {
971*795d594fSAndroid Build Coastguard Worker           ArtMethod* method = cur_shadow_frame_->GetMethod();
972*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "Tid=" << thread_-> GetThreadId() << ", method: "
973*795d594fSAndroid Build Coastguard Worker               << ArtMethod::PrettyMethod(method) << "@" << method
974*795d594fSAndroid Build Coastguard Worker               << ", ShadowFrame";
975*795d594fSAndroid Build Coastguard Worker         }
976*795d594fSAndroid Build Coastguard Worker         ValidateFrame();
977*795d594fSAndroid Build Coastguard Worker         bool should_continue = VisitFrame();
978*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(!should_continue)) {
979*795d594fSAndroid Build Coastguard Worker           return;
980*795d594fSAndroid Build Coastguard Worker         }
981*795d594fSAndroid Build Coastguard Worker         cur_depth_++;
982*795d594fSAndroid Build Coastguard Worker         cur_shadow_frame_ = cur_shadow_frame_->GetLink();
983*795d594fSAndroid Build Coastguard Worker       } while (cur_shadow_frame_ != nullptr);
984*795d594fSAndroid Build Coastguard Worker     }
985*795d594fSAndroid Build Coastguard Worker     if (include_transitions) {
986*795d594fSAndroid Build Coastguard Worker       bool should_continue = VisitFrame();
987*795d594fSAndroid Build Coastguard Worker       if (!should_continue) {
988*795d594fSAndroid Build Coastguard Worker         return;
989*795d594fSAndroid Build Coastguard Worker       }
990*795d594fSAndroid Build Coastguard Worker     }
991*795d594fSAndroid Build Coastguard Worker     if (kCount == CountTransitions::kYes) {
992*795d594fSAndroid Build Coastguard Worker       cur_depth_++;
993*795d594fSAndroid Build Coastguard Worker     }
994*795d594fSAndroid Build Coastguard Worker   }
995*795d594fSAndroid Build Coastguard Worker   if (num_frames_ != 0) {
996*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(cur_depth_, num_frames_);
997*795d594fSAndroid Build Coastguard Worker   }
998*795d594fSAndroid Build Coastguard Worker }
999*795d594fSAndroid Build Coastguard Worker 
1000*795d594fSAndroid Build Coastguard Worker template void StackVisitor::WalkStack<StackVisitor::CountTransitions::kYes>(bool);
1001*795d594fSAndroid Build Coastguard Worker template void StackVisitor::WalkStack<StackVisitor::CountTransitions::kNo>(bool);
1002*795d594fSAndroid Build Coastguard Worker 
1003*795d594fSAndroid Build Coastguard Worker }  // namespace art
1004