• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &regInfo : 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