• 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 ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H
17 #define ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H
18 
19 #include "ecmascript/frames.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/mem/heap.h"
23 #include "ecmascript/mem/visitor.h"
24 #include "ecmascript/method.h"
25 
26 namespace panda {
27 namespace ecmascript {
28 class JSThread;
29 class ConstantPool;
30 namespace kungfu {
31     class ArkStackMapParser;
32 };
33 
34 class FrameHandler {
35 public:
36     explicit FrameHandler(const JSThread *thread);
37 
38     ~FrameHandler() = default;
39 
40     DEFAULT_COPY_SEMANTIC(FrameHandler);
41     DEFAULT_MOVE_SEMANTIC(FrameHandler);
42 
HasFrame()43     bool HasFrame() const
44     {
45         return sp_ != nullptr;
46     }
47 
GetFrameType(const JSTaggedType * sp)48     inline static FrameType GetFrameType(const JSTaggedType *sp)
49     {
50         ASSERT(sp != nullptr);
51         FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp) - sizeof(FrameType));
52         return *typeAddr;
53     }
54 
IsEntryFrame(const uint8_t * pc)55     inline static bool IsEntryFrame(const uint8_t *pc)
56     {
57         return pc == nullptr;
58     }
59 
IsEntryFrame()60     bool IsEntryFrame() const
61     {
62         ASSERT(HasFrame());
63         // The structure of InterpretedFrame, AsmInterpretedFrame, InterpretedEntryFrame is the same, order is pc, base.
64         FrameType type = GetFrameType();
65         if (type == FrameType::BUILTIN_ENTRY_FRAME ||
66             type == FrameType::INTERPRETER_ENTRY_FRAME ||
67             type == FrameType::ASM_INTERPRETER_ENTRY_FRAME ||
68             type == FrameType::OPTIMIZED_ENTRY_FRAME) {
69                 return true;
70         } else if (type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME ||
71                    type == FrameType::INTERPRETER_FRAME) {
72             FrameIterator it(sp_);
73             InterpretedFrame *state = it.GetFrame<InterpretedFrame>();
74             return state->GetPc() == nullptr;
75         }
76         return false;
77     }
78 
IsInterpretedFrame()79     bool IsInterpretedFrame() const
80     {
81         FrameType type = GetFrameType();
82         return IsInterpretedFrame(type);
83     }
84 
IsInterpretedFrame(FrameType type)85     bool IsInterpretedFrame(FrameType type) const
86     {
87         return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
88     }
89 
IsJSFrame()90     bool IsJSFrame() const
91     {
92         FrameType type = GetFrameType();
93         return IsJSFrame(type);
94     }
95 
IsOptimizedJSFunctionFrame()96     bool IsOptimizedJSFunctionFrame() const
97     {
98         FrameType type = GetFrameType();
99         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
100             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
101     }
102 
IsJSFrame(FrameType type)103     bool IsJSFrame(FrameType type) const
104     {
105         return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type);
106     }
107 
IsOptimizedJSFunctionFrame(FrameType type)108     bool IsOptimizedJSFunctionFrame(FrameType type) const
109     {
110         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
111             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
112     }
113 
IsFastJitFunctionFrame(FrameType type)114     bool IsFastJitFunctionFrame(FrameType type) const
115     {
116         return type == FrameType::FASTJIT_FUNCTION_FRAME ||
117             type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
118     }
119 
IsAsmInterpretedFrame()120     bool IsAsmInterpretedFrame() const
121     {
122         FrameIterator it(sp_, thread_);
123         FrameType type = it.GetFrameType();
124         return (type == FrameType::ASM_INTERPRETER_FRAME) ||
125             (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
126     }
127 
IsAsmInterpretedFrame(FrameType type)128     bool IsAsmInterpretedFrame(FrameType type) const
129     {
130         return (type == FrameType::ASM_INTERPRETER_FRAME) ||
131             (type == FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
132     }
IsBuiltinFrame()133     bool IsBuiltinFrame() const
134     {
135         FrameType type = GetFrameType();
136         return (type >= FrameType::BUILTIN_FIRST) && (type <= FrameType::BUILTIN_LAST);
137     }
IsBuiltinEntryFrame()138     bool IsBuiltinEntryFrame() const
139     {
140         return (GetFrameType() == FrameType::BUILTIN_ENTRY_FRAME);
141     }
142 
IsInterpretedEntryFrame()143     bool IsInterpretedEntryFrame() const
144     {
145         if (thread_->IsAsmInterpreter()) {
146             FrameType type = GetFrameType();
147             return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
148         }
149         return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME);
150     }
151 
IsInterpretedEntryFrame(FrameType type)152     bool IsInterpretedEntryFrame(FrameType type) const
153     {
154         if (thread_->IsAsmInterpreter()) {
155             return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
156         }
157         return (type == FrameType::INTERPRETER_ENTRY_FRAME);
158     }
159 
IsAsmInterpretedEntryFrame()160     bool IsAsmInterpretedEntryFrame() const
161     {
162         FrameType type = GetFrameType();
163         return IsAsmInterpretedEntryFrame(type);
164     }
165 
IsAsmInterpretedEntryFrame(FrameType type)166     bool IsAsmInterpretedEntryFrame(FrameType type) const
167     {
168         return (type == FrameType::ASM_INTERPRETER_ENTRY_FRAME || type == FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
169     }
170 
IsCInterpretedEntryFrame()171     bool IsCInterpretedEntryFrame() const
172     {
173         return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME);
174     }
175 
IsCInterpretedEntryFrame(FrameType type)176     bool IsCInterpretedEntryFrame(FrameType type) const
177     {
178         return (type == FrameType::INTERPRETER_ENTRY_FRAME);
179     }
180 
IsOptimizedEntryFrame(FrameType type)181     bool IsOptimizedEntryFrame(FrameType type) const
182     {
183         return type == FrameType::OPTIMIZED_ENTRY_FRAME;
184     }
185 
IsJSEntryFrame(FrameType type)186     bool IsJSEntryFrame(FrameType type) const
187     {
188         return IsAsmInterpretedEntryFrame(type) || IsOptimizedEntryFrame(type);
189     }
190 
IsLeaveFrame()191     bool IsLeaveFrame() const
192     {
193         FrameType type = GetFrameType();
194         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
195     }
196 
IsInterpreterBuiltinFrame()197     bool IsInterpreterBuiltinFrame() const
198     {
199         FrameType type = GetFrameType();
200         return type == FrameType::INTERPRETER_BUILTIN_FRAME;
201     }
202 
IsBaselineBuiltinFrame(FrameType type)203     bool IsBaselineBuiltinFrame(FrameType type) const
204     {
205         return (type == FrameType::BASELINE_BUILTIN_FRAME);
206     }
207 
GetSp()208     JSTaggedType *GetSp() const
209     {
210         return sp_;
211     }
212 
GetFp()213     JSTaggedType *GetFp() const
214     {
215         return fp_;
216     }
217 
GetBaselineNativePc()218     uintptr_t GetBaselineNativePc() const
219     {
220         return baselineNativePc_;
221     }
222 
223     void PrevJSFrame();
224     JSTaggedType *GetPrevJSFrame();
225 
226     // for InterpretedFrame.
227     JSTaggedValue GetVRegValue(size_t index) const;
228     void SetVRegValue(size_t index, JSTaggedValue value);
229 
230     // for BaselineBuiltinFrame
231     void FindAndSetBaselineNativePc(FrameIterator it);
232 
233     JSTaggedValue GetEnv() const;
234     JSTaggedValue GetAcc() const;
235     uint32_t GetNumberArgs();
236     uint32_t GetBytecodeOffset() const;
237     Method *GetMethod() const;
238     const JSPandaFile* GetJSPandaFile() const;
239     std::string GetFileName() const;
240     uint32_t GetAbcId() const;
241     uint32_t GetMethodId() const;
242     Method *CheckAndGetMethod() const;
243     JSTaggedValue GetThis() const;
244     JSTaggedValue GetFunction() const;
245     const uint8_t *GetPc() const;
246     ConstantPool *GetConstpool() const;
247 
248     void DumpStack(std::ostream &os) const;
DumpStack()249     void DumpStack() const
250     {
251         DumpStack(std::cout);
252     }
253 
254     void DumpPC(std::ostream &os, const uint8_t *pc) const;
DumpPC(const uint8_t * pc)255     void DumpPC(const uint8_t *pc) const
256     {
257         DumpPC(std::cout, pc);
258     }
259 
260     // for Frame GC.
261     void Iterate(RootVisitor &visitor);
262     void IterateFrameChain(JSTaggedType *start, RootVisitor &visitor) const;
263     void IterateAssembleStack(RootVisitor &visitor);
264     void IterateEcmaRuntimeCallInfo(RootVisitor &visitor);
265 
266 private:
GetFrameType()267     FrameType GetFrameType() const
268     {
269         ASSERT(HasFrame());
270         FrameType *typeAddr = reinterpret_cast<FrameType *>(reinterpret_cast<uintptr_t>(sp_) - sizeof(FrameType));
271         return *typeAddr;
272     }
273 
274     void AdvanceToJSFrame();
275     uintptr_t GetInterpretedFrameEnd(JSTaggedType *prevSp) const;
276 private:
277     JSTaggedType *sp_ {nullptr};
278     JSTaggedType *fp_ {nullptr};
279     uintptr_t baselineNativePc_ {0}; // For baselineJit upFrame
280     const JSThread *thread_ {nullptr};
281     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
282 };
283 
284 class StackAssertScope {
285 public:
StackAssertScope(JSThread * thread)286     explicit StackAssertScope(JSThread *thread) : thread_(thread), oldSp_(thread->GetCurrentSPFrame()) {}
287 
~StackAssertScope()288     ~StackAssertScope()
289     {
290         if (!thread_->HasPendingException()) {
291             DASSERT_PRINT(oldSp_ == thread_->GetCurrentSPFrame(),
292                           "StackAssertScope assert failed, sp did not restore as expeted");
293         }
294     }
295 
296 private:
297     JSThread *thread_ {nullptr};
298     const JSTaggedType *oldSp_ {nullptr};
299 };
300 }; // namespace ecmascript
301 }  // namespace panda
302 #endif  // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H
303