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