1 /**
2 * Copyright (c) 2021-2024 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 ark {
24
25 template <bool OBJECTS, bool WITH_REG_INFO, class VRegRef, typename Func>
26 // NOLINTNEXTLINE(google-runtime-references)
InvokeCallback(Func func,compiler::VRegInfo regInfo,VRegRef & vreg)27 bool InvokeCallback(Func func, [[maybe_unused]] compiler::VRegInfo regInfo, VRegRef &vreg)
28 {
29 if (OBJECTS && !vreg.HasObject()) {
30 return true;
31 }
32 if constexpr (WITH_REG_INFO) { // NOLINT
33 if (!func(regInfo, 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 codeInfo_.GetVRegList(stackmap_, inlineDepth_, mem::InternalAllocator<>::GetInternalAllocatorFromRuntime());
50
51 for (auto ®Info : regs) {
52 if (!regInfo.IsLive()) {
53 continue;
54 }
55 interpreter::VRegister vreg0;
56 interpreter::VRegister vreg1;
57 interpreter::StaticVRegisterRef resReg(&vreg0, &vreg1);
58 cframe.GetVRegValue(regInfo, codeInfo_, calleeStack_.stack.data(), resReg);
59 if (!InvokeCallback<false, WITH_REG_INFO>(func, regInfo, resReg)) {
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 regInfo : CFrameStaticNativeMethodIterator<RUNTIME_ARCH>::MakeRange(&cframe)) {
76 interpreter::VRegister vreg0;
77 interpreter::VRegister vreg1;
78 interpreter::StaticVRegisterRef resReg(&vreg0, &vreg1);
79 cframe.GetVRegValue(regInfo, codeInfo_, calleeStack_.stack.data(), resReg);
80 if (!InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, resReg)) {
81 return false;
82 }
83 }
84 return true;
85 }
86
87 if (OBJECTS) {
88 codeInfo_.EnumerateStaticRoots(stackmap_, [this, &cframe, &func](VRegInfo regInfo) {
89 interpreter::VRegister vreg0;
90 interpreter::VRegister vreg1;
91 interpreter::StaticVRegisterRef resReg(&vreg0, &vreg1);
92 cframe.GetVRegValue(regInfo, codeInfo_, calleeStack_.stack.data(), resReg);
93 return !resReg.HasObject() || InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, resReg);
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 regInfo : CFrameDynamicNativeMethodIterator<RUNTIME_ARCH>::MakeRange(&cframe)) {
110 interpreter::VRegister vreg0;
111 interpreter::DynamicVRegisterRef resReg(&vreg0);
112 cframe.GetVRegValue(regInfo, codeInfo_, calleeStack_.stack.data(), resReg);
113 if (!InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, resReg)) {
114 return false;
115 }
116 }
117 return true;
118 }
119
120 if (OBJECTS) {
121 codeInfo_.EnumerateDynamicRoots(stackmap_, [this, &cframe, &func](VRegInfo regInfo) {
122 interpreter::VRegister vreg0;
123 interpreter::DynamicVRegisterRef resReg(&vreg0);
124 cframe.GetVRegValue(regInfo, codeInfo_, calleeStack_.stack.data(), resReg);
125 return !resReg.HasObject() || InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, resReg);
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 frameHandler,Func func)135 bool StackWalker::IterateRegsForIFrameInternal(F frameHandler, Func func)
136 {
137 for (size_t i = 0; i < frameHandler.GetSize(); i++) {
138 auto vreg = frameHandler.GetVReg(i);
139 if (OBJECTS && !vreg.HasObject()) {
140 continue;
141 }
142 auto type = vreg.HasObject() ? OBJ_TYPE : PRIMITIVE_TYPE;
143 VRegInfo regInfo(0, VRegInfo::Location::SLOT, type, VRegInfo::VRegType::VREG, i);
144 if (!InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, vreg)) {
145 return false;
146 }
147 }
148
149 auto acc = frameHandler.GetAccAsVReg();
150 auto type = acc.HasObject() ? OBJ_TYPE : PRIMITIVE_TYPE;
151 VRegInfo regInfo(0, VRegInfo::Location::SLOT, type, VRegInfo::VRegType::ACC, 0);
152 return InvokeCallback<OBJECTS, WITH_REG_INFO>(func, regInfo, 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 frameHandler(frame);
161 ASSERT(IsDynamicMethod());
162 return IterateRegsForIFrameInternal<OBJECTS, WITH_REG_INFO, VRegInfo::Type::ANY, VRegInfo::Type::ANY>(
163 frameHandler, func);
164 }
165 StaticFrameHandler frameHandler(frame);
166 return IterateRegsForIFrameInternal<OBJECTS, WITH_REG_INFO, VRegInfo::Type::OBJECT, VRegInfo::Type::INT64>(
167 frameHandler, func);
168 }
169
170 template <bool OBJECTS, bool WITH_REG_INFO, typename Func>
IterateRegs(Func func)171 bool StackWalker::IterateRegs(Func func)
172 {
173 if (IsCFrame()) {
174 if (IsDynamicMethod()) {
175 return IterateRegsForCFrameDynamic<OBJECTS, WITH_REG_INFO>(func);
176 }
177 return IterateRegsForCFrameStatic<OBJECTS, WITH_REG_INFO>(func);
178 }
179 return IterateRegsForIFrame<OBJECTS, WITH_REG_INFO>(func);
180 }
181
182 } // namespace ark
183
184 #endif // PANDA_RUNTIME_STACK_WALKER_INL_H
185