• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_RUNTIME_STACK_WALKER_INL_H
17 #define PANDA_RUNTIME_STACK_WALKER_INL_H
18 
19 #include "stack_walker.h"
20 #include "runtime/include/cframe_iterators.h"
21 #include "compiler/code_info/code_info.h"
22 
23 namespace panda {
24 
25 template <bool objects, bool with_reg_info, class VRegRef, typename Func>
26 // NOLINTNEXTLINE(google-runtime-references)
InvokeCallback(Func func,compiler::VRegInfo reg_info,VRegRef & vreg)27 bool InvokeCallback(Func func, [[maybe_unused]] compiler::VRegInfo reg_info, VRegRef &vreg)
28 {
29     if (objects && !vreg.HasObject()) {
30         return true;
31     }
32     if constexpr (with_reg_info) {  // NOLINT
33         if (!func(reg_info, vreg)) {
34             return false;
35         }
36     } else {  // NOLINT
37         if (!func(vreg)) {
38             return false;
39         }
40     }
41     return true;
42 }
43 
44 template <bool with_reg_info, typename Func>
IterateAllRegsForCFrame(Func func)45 bool StackWalker::IterateAllRegsForCFrame(Func func)
46 {
47     auto &cframe = GetCFrame();
48     const auto regs =
49         code_info_.GetVRegList(stackmap_, inline_depth_, mem::InternalAllocator<>::GetInternalAllocatorFromRuntime());
50 
51     for (auto &reg_info : regs) {
52         if (!reg_info.IsLive()) {
53             continue;
54         }
55         interpreter::VRegister vreg0;
56         interpreter::VRegister vreg1;
57         interpreter::StaticVRegisterRef res_reg(&vreg0, &vreg1);
58         cframe.GetVRegValue(reg_info, code_info_, callee_stack_.stack.data(), res_reg);
59         if (!InvokeCallback<false, with_reg_info>(func, reg_info, res_reg)) {
60             return false;
61         }
62     }
63 
64     return true;
65 }
66 
67 template <bool objects, bool with_reg_info, typename Func>
IterateRegsForCFrameStatic(Func func)68 bool StackWalker::IterateRegsForCFrameStatic(Func func)
69 {
70     ASSERT(IsCFrame());
71     ASSERT(!IsDynamicMethod());
72     auto &cframe = GetCFrame();
73 
74     if (cframe.IsNativeMethod()) {
75         for (auto reg_info : CFrameStaticNativeMethodIterator<RUNTIME_ARCH>::MakeRange(&cframe)) {
76             interpreter::VRegister vreg0;
77             interpreter::VRegister vreg1;
78             interpreter::StaticVRegisterRef res_reg(&vreg0, &vreg1);
79             cframe.GetVRegValue(reg_info, code_info_, callee_stack_.stack.data(), res_reg);
80             if (!InvokeCallback<objects, with_reg_info>(func, reg_info, res_reg)) {
81                 return false;
82             }
83         }
84         return true;
85     }
86 
87     if (objects) {
88         code_info_.EnumerateStaticRoots(stackmap_, [this, &cframe, &func](VRegInfo reg_info) {
89             interpreter::VRegister vreg0;
90             interpreter::VRegister vreg1;
91             interpreter::StaticVRegisterRef res_reg(&vreg0, &vreg1);
92             cframe.GetVRegValue(reg_info, code_info_, callee_stack_.stack.data(), res_reg);
93             return !res_reg.HasObject() || InvokeCallback<objects, with_reg_info>(func, reg_info, res_reg);
94         });
95         return true;
96     }
97 
98     return IterateAllRegsForCFrame<with_reg_info>(func);
99 }
100 
101 template <bool objects, bool with_reg_info, typename Func>
IterateRegsForCFrameDynamic(Func func)102 bool StackWalker::IterateRegsForCFrameDynamic(Func func)
103 {
104     ASSERT(IsCFrame());
105     ASSERT(IsDynamicMethod());
106     auto &cframe = GetCFrame();
107 
108     if (cframe.IsNativeMethod()) {
109         for (auto reg_info : CFrameDynamicNativeMethodIterator<RUNTIME_ARCH>::MakeRange(&cframe)) {
110             interpreter::VRegister vreg0;
111             interpreter::DynamicVRegisterRef res_reg(&vreg0);
112             cframe.GetVRegValue(reg_info, code_info_, callee_stack_.stack.data(), res_reg);
113             if (!InvokeCallback<objects, with_reg_info>(func, reg_info, res_reg)) {
114                 return false;
115             }
116         }
117         return true;
118     }
119 
120     if (objects) {
121         code_info_.EnumerateDynamicRoots(stackmap_, [this, &cframe, &func](VRegInfo reg_info) {
122             interpreter::VRegister vreg0;
123             interpreter::DynamicVRegisterRef res_reg(&vreg0);
124             cframe.GetVRegValue(reg_info, code_info_, callee_stack_.stack.data(), res_reg);
125             return !res_reg.HasObject() || InvokeCallback<objects, with_reg_info>(func, reg_info, res_reg);
126         });
127         return true;
128     }
129 
130     return IterateAllRegsForCFrame<with_reg_info>(func);
131 }
132 
133 template <bool objects, bool with_reg_info, StackWalker::VRegInfo::Type obj_type,
134           StackWalker::VRegInfo::Type primitive_type, class F, typename Func>
IterateRegsForIFrameInternal(F frame_handler,Func func)135 bool StackWalker::IterateRegsForIFrameInternal(F frame_handler, Func func)
136 {
137     for (size_t i = 0; i < frame_handler.GetSize(); i++) {
138         auto vreg = frame_handler.GetVReg(i);
139         if (objects && !vreg.HasObject()) {
140             continue;
141         }
142         auto type = vreg.HasObject() ? obj_type : primitive_type;
143         VRegInfo reg_info(0, VRegInfo::Location::SLOT, type, false, i);
144         if (!InvokeCallback<objects, with_reg_info>(func, reg_info, vreg)) {
145             return false;
146         }
147     }
148 
149     auto acc = frame_handler.GetAccAsVReg();
150     auto type = acc.HasObject() ? obj_type : primitive_type;
151     VRegInfo reg_info(0, VRegInfo::Location::SLOT, type, true, 0);
152     return InvokeCallback<objects, with_reg_info>(func, reg_info, acc);
153 }
154 
155 template <bool objects, bool with_reg_info, typename Func>
IterateRegsForIFrame(Func func)156 bool StackWalker::IterateRegsForIFrame(Func func)
157 {
158     auto frame = GetIFrame();
159     if (frame->IsDynamic()) {
160         DynamicFrameHandler frame_handler(frame);
161         return IterateRegsForIFrameInternal<objects, with_reg_info, VRegInfo::Type::ANY, VRegInfo::Type::ANY>(
162             frame_handler, func);
163     }
164     StaticFrameHandler frame_handler(frame);
165     return IterateRegsForIFrameInternal<objects, with_reg_info, VRegInfo::Type::OBJECT, VRegInfo::Type::INT64>(
166         frame_handler, func);
167 }
168 
169 template <bool objects, bool with_reg_info, typename Func>
IterateRegs(Func func)170 bool StackWalker::IterateRegs(Func func)
171 {
172     if (IsCFrame()) {
173         if (IsDynamicMethod()) {
174             return IterateRegsForCFrameDynamic<objects, with_reg_info>(func);
175         }
176         return IterateRegsForCFrameStatic<objects, with_reg_info>(func);
177     }
178     return IterateRegsForIFrame<objects, with_reg_info>(func);
179 }
180 
181 }  // namespace panda
182 
183 #endif  // PANDA_RUNTIME_STACK_WALKER_INL_H
184