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