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 #include "runtime/tooling/sampler/stack_walker_base.h"
17
18 namespace ark {
19
20 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
StackWalkerBase(void * fp,bool isFrameCompiled)21 StackWalkerBase::StackWalkerBase(void *fp, bool isFrameCompiled)
22 {
23 frame_ = GetTopFrameFromFp(fp, isFrameCompiled);
24 }
25
GetTopFrameFromFp(void * ptr,bool isFrameCompiled)26 StackWalkerBase::FrameVariant StackWalkerBase::GetTopFrameFromFp(void *ptr, bool isFrameCompiled)
27 {
28 if (isFrameCompiled) {
29 if (IsBoundaryFrame<FrameKind::INTERPRETER>(ptr)) {
30 auto bp = GetPrevFromBoundary<FrameKind::INTERPRETER>(ptr);
31 if (GetBoundaryFrameMethod<FrameKind::COMPILER>(bp) == BYPASS) {
32 return CreateCFrame(GetPrevFromBoundary<FrameKind::COMPILER>(bp));
33 }
34 return CreateCFrame(GetPrevFromBoundary<FrameKind::INTERPRETER>(ptr)); // NOLINT
35 }
36 return CreateCFrame(reinterpret_cast<SlotType *>(ptr));
37 }
38 return reinterpret_cast<Frame *>(ptr);
39 }
40
CreateCFrame(SlotType * ptr)41 StackWalkerBase::CFrameType StackWalkerBase::CreateCFrame(SlotType *ptr)
42 {
43 CFrameType cframe(ptr);
44 return cframe;
45 }
46
NextFrame()47 void StackWalkerBase::NextFrame()
48 {
49 if (IsCFrame()) {
50 NextFromCFrame();
51 } else {
52 NextFromIFrame();
53 }
54 }
55
CreateCFrameForC2IBridge(Frame * frame)56 StackWalkerBase::CFrameType StackWalkerBase::CreateCFrameForC2IBridge(Frame *frame)
57 {
58 auto prev = GetPrevFromBoundary<FrameKind::INTERPRETER>(frame);
59 ASSERT(GetBoundaryFrameMethod<FrameKind::COMPILER>(prev) != FrameBridgeKind::BYPASS);
60 return CreateCFrame(reinterpret_cast<SlotType *>(prev));
61 }
62
NextFromCFrame()63 void StackWalkerBase::NextFromCFrame()
64 {
65 auto prev = GetCFrame().GetPrevFrame();
66 if (prev == nullptr) {
67 frame_ = nullptr;
68 return;
69 }
70 auto frameMethod = GetBoundaryFrameMethod<FrameKind::COMPILER>(prev);
71 switch (frameMethod) {
72 case FrameBridgeKind::INTERPRETER_TO_COMPILED_CODE: {
73 auto prevFrame = reinterpret_cast<Frame *>(GetPrevFromBoundary<FrameKind::COMPILER>(prev));
74 if (prevFrame != nullptr && IsBoundaryFrame<FrameKind::INTERPRETER>(prevFrame)) {
75 frame_ = CreateCFrameForC2IBridge(prevFrame);
76 break;
77 }
78 frame_ = reinterpret_cast<Frame *>(prevFrame);
79 break;
80 }
81 case FrameBridgeKind::BYPASS: {
82 auto prevFrame = reinterpret_cast<Frame *>(GetPrevFromBoundary<FrameKind::COMPILER>(prev));
83 if (prevFrame != nullptr && IsBoundaryFrame<FrameKind::INTERPRETER>(prevFrame)) {
84 frame_ = CreateCFrameForC2IBridge(prevFrame);
85 break;
86 }
87 frame_ = CreateCFrame(reinterpret_cast<SlotType *>(GetPrevFromBoundary<FrameKind::COMPILER>(prev)));
88 break;
89 }
90 default:
91 frame_ = CreateCFrame(reinterpret_cast<SlotType *>(prev));
92 break;
93 }
94 }
95
NextFromIFrame()96 void StackWalkerBase::NextFromIFrame()
97 {
98 auto prev = GetIFrame()->GetPrevFrame();
99 if (prev == nullptr) {
100 frame_ = nullptr;
101 return;
102 }
103 if (IsBoundaryFrame<FrameKind::INTERPRETER>(prev)) {
104 auto bp = GetPrevFromBoundary<FrameKind::INTERPRETER>(prev);
105 if (GetBoundaryFrameMethod<FrameKind::COMPILER>(bp) == BYPASS) {
106 frame_ = CreateCFrame(GetPrevFromBoundary<FrameKind::COMPILER>(bp));
107 } else {
108 frame_ = CreateCFrameForC2IBridge(prev);
109 }
110 } else {
111 frame_ = reinterpret_cast<Frame *>(prev);
112 }
113 }
114
115 } // namespace ark
116