• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_INTERPRETER_FRAME_H_
17 #define PANDA_RUNTIME_INTERPRETER_FRAME_H_
18 
19 #include <cstddef>
20 #include <cstdint>
21 
22 #include "libpandabase/macros.h"
23 #include "libpandabase/utils/bit_helpers.h"
24 #include "libpandabase/utils/bit_utils.h"
25 #include "libpandabase/utils/logger.h"
26 #include "runtime/interpreter/vregister-inl.h"
27 #include "libpandafile/bytecode_instruction-inl.h"
28 
29 namespace panda {
30 
31 class Method;
32 class ObjectHeader;
33 
34 class Frame {
35 public:
36     class VRegister : public interpreter::VRegisterIface<VRegister> {
37     public:
38         VRegister() = default;
39 
VRegister(int64_t v,uint64_t tag)40         ALWAYS_INLINE inline VRegister(int64_t v, uint64_t tag)
41         {
42             SetValue(v);
43             SetTag(tag);
44         }
45 
SetValue(int64_t v)46         ALWAYS_INLINE inline void SetValue(int64_t v)
47         {
48             v_ = v;
49         }
50 
GetValue()51         ALWAYS_INLINE inline int64_t GetValue() const
52         {
53             return v_;
54         }
55 
SetTag(uint64_t tag)56         ALWAYS_INLINE inline void SetTag(uint64_t tag)
57         {
58             tag_ = tag;
59         }
60 
GetTag()61         ALWAYS_INLINE inline uint64_t GetTag() const
62         {
63             return tag_;
64         }
65 
GetTagSize()66         ALWAYS_INLINE static inline constexpr uint32_t GetTagSize()
67         {
68             return sizeof(tag_);
69         }
70 
GetValueOffset()71         ALWAYS_INLINE static inline constexpr uint32_t GetValueOffset()
72         {
73             return MEMBER_OFFSET(VRegister, v_);
74         }
75 
GetTagOffset()76         ALWAYS_INLINE static inline constexpr uint32_t GetTagOffset()
77         {
78             return MEMBER_OFFSET(VRegister, tag_);
79         }
80 
81         ~VRegister() = default;
82 
83         DEFAULT_COPY_SEMANTIC(VRegister);
84         DEFAULT_MOVE_SEMANTIC(VRegister);
85 
86     private:
87         // Stores the bit representation of the register value, regardless of the real type.
88         // It can contain int/uint 8/16/32/64, float, double and ObjectHeader *.
89         int64_t v_ {0};
90         uint64_t tag_ {0};
91     };
92 
93     // Instrumentation: indicate what the frame must be force poped
94     static constexpr size_t FORCE_POP = 1U;
95     // Instrumentation: indicate what the frame must retry last instruction
96     static constexpr size_t RETRY_INSTRUCTION = 2U;
97     // Instrumentation: indicate what the frame must notify when poped
98     static constexpr size_t NOTIFY_POP = 4U;
99     // Indicate that the frame was created after deoptimization.
100     // This flag is needed to avoid OSR for deoptimized frames. Because the OSR consumes stack that isn't released after
101     // deoptimization, stack overflow may occur. This constrain may be removed once asm interpreter is introduced.
102     static constexpr size_t IS_DEOPTIMIZED = 8U;
103     // Indicate whether this frame is stackless frame, only take effects under stackless interpreter mode.
104     static constexpr size_t IS_STACKLESS = 16U;
105     // Indicate whether this frame is initobj frame, only take effects under stackless interpreter mode.
106     static constexpr size_t IS_INITOBJ = 32U;
107 
Frame(Method * method,Frame * prev,uint32_t nregs)108     ALWAYS_INLINE inline Frame(Method *method, Frame *prev, uint32_t nregs)
109         : prev_(prev),
110           method_(method),
111           nregs_(nregs),
112           num_actual_args_(0),
113           bc_offset_(0),
114           flags_(0),
115           next_inst_(nullptr),
116           inst_(nullptr)
117     {
118     }
Frame(Method * method,Frame * prev,uint32_t nregs,uint32_t num_actual_args)119     ALWAYS_INLINE inline Frame(Method *method, Frame *prev, uint32_t nregs, uint32_t num_actual_args)
120         : prev_(prev),
121           method_(method),
122           nregs_(nregs),
123           num_actual_args_(num_actual_args),
124           bc_offset_(0),
125           flags_(0),
126           next_inst_(nullptr),
127           inst_(nullptr)
128     {
129     }
130 
GetVReg(size_t i)131     ALWAYS_INLINE inline const VRegister &GetVReg(size_t i) const
132     {
133         return vregs_[i];
134     }
135 
GetVReg(size_t i)136     ALWAYS_INLINE inline VRegister &GetVReg(size_t i)
137     {
138         return vregs_[i];
139     }
140 
SetAcc(const VRegister & acc)141     ALWAYS_INLINE inline void SetAcc(const VRegister &acc)
142     {
143         acc_ = acc;
144     }
145 
GetAcc()146     ALWAYS_INLINE inline VRegister &GetAcc()
147     {
148         return acc_;
149     }
150 
GetAcc()151     ALWAYS_INLINE inline const VRegister &GetAcc() const
152     {
153         return acc_;
154     }
155 
SetMethod(Method * method)156     ALWAYS_INLINE inline void SetMethod(Method *method)
157     {
158         method_ = method;
159     }
160 
GetMethod()161     ALWAYS_INLINE inline Method *GetMethod() const
162     {
163         return method_;
164     }
165 
166     ALWAYS_INLINE const uint8_t *GetInstrOffset();
167 
SetPrevFrame(Frame * prev)168     ALWAYS_INLINE inline void SetPrevFrame(Frame *prev)
169     {
170         prev_ = prev;
171     }
172 
GetPrevFrame()173     ALWAYS_INLINE inline Frame *GetPrevFrame() const
174     {
175         return prev_;
176     }
177 
GetSize()178     ALWAYS_INLINE inline uint32_t GetSize() const
179     {
180         return nregs_;
181     }
182 
GetNumActualArgs()183     ALWAYS_INLINE inline uint32_t GetNumActualArgs() const
184     {
185         return num_actual_args_;
186     }
187 
SetBytecodeOffset(uint32_t bc_offset)188     ALWAYS_INLINE inline void SetBytecodeOffset(uint32_t bc_offset)
189     {
190         bc_offset_ = bc_offset;
191     }
192 
GetBytecodeOffset()193     ALWAYS_INLINE inline uint32_t GetBytecodeOffset() const
194     {
195         return bc_offset_;
196     }
197 
SetNextInstruction(BytecodeInstruction inst)198     ALWAYS_INLINE inline void SetNextInstruction(BytecodeInstruction inst)
199     {
200         next_inst_ = inst;
201     }
202 
GetNextInstruction()203     ALWAYS_INLINE inline BytecodeInstruction GetNextInstruction() const
204     {
205         return next_inst_;
206     }
207 
SetInstruction(const uint8_t * inst)208     ALWAYS_INLINE inline void SetInstruction(const uint8_t *inst)
209     {
210         inst_ = inst;
211     }
212 
GetInstruction()213     ALWAYS_INLINE inline const uint8_t *GetInstruction() const
214     {
215         return inst_;
216     }
217 
GetSize(size_t nregs)218     ALWAYS_INLINE static inline size_t GetSize(size_t nregs)
219     {
220         return AlignUp(sizeof(Frame) + sizeof(VRegister) * nregs, GetAlignmentInBytes(DEFAULT_FRAME_ALIGNMENT));
221     }
222 
IsForcePop()223     ALWAYS_INLINE inline bool IsForcePop() const
224     {
225         return (flags_ & FORCE_POP) != 0;
226     }
227 
ClearForcePop()228     ALWAYS_INLINE inline void ClearForcePop()
229     {
230         flags_ = flags_ & ~FORCE_POP;
231     }
232 
SetForcePop()233     ALWAYS_INLINE inline void SetForcePop()
234     {
235         flags_ = flags_ | FORCE_POP;
236     }
237 
IsRetryInstruction()238     ALWAYS_INLINE inline bool IsRetryInstruction() const
239     {
240         return (flags_ & RETRY_INSTRUCTION) != 0;
241     }
242 
ClearRetryInstruction()243     ALWAYS_INLINE inline void ClearRetryInstruction()
244     {
245         flags_ = flags_ & ~RETRY_INSTRUCTION;
246     }
247 
SetRetryInstruction()248     ALWAYS_INLINE inline void SetRetryInstruction()
249     {
250         flags_ = flags_ | RETRY_INSTRUCTION;
251     }
252 
IsNotifyPop()253     ALWAYS_INLINE inline bool IsNotifyPop() const
254     {
255         return (flags_ & NOTIFY_POP) != 0;
256     }
257 
ClearNotifyPop()258     ALWAYS_INLINE inline void ClearNotifyPop()
259     {
260         flags_ = flags_ & ~NOTIFY_POP;
261     }
262 
SetNotifyPop()263     ALWAYS_INLINE inline void SetNotifyPop()
264     {
265         flags_ = flags_ | NOTIFY_POP;
266     }
267 
IsDeoptimized()268     ALWAYS_INLINE inline bool IsDeoptimized() const
269     {
270         return (flags_ & IS_DEOPTIMIZED) != 0;
271     }
272 
SetDeoptimized()273     ALWAYS_INLINE inline void SetDeoptimized()
274     {
275         flags_ |= IS_DEOPTIMIZED;
276     }
277 
DisableOsr()278     ALWAYS_INLINE inline void DisableOsr()
279     {
280         SetDeoptimized();
281     }
282 
IsStackless()283     ALWAYS_INLINE inline bool IsStackless() const
284     {
285         return (flags_ & IS_STACKLESS) != 0;
286     }
287 
SetStackless()288     ALWAYS_INLINE inline void SetStackless()
289     {
290         flags_ = flags_ | IS_STACKLESS;
291     }
292 
IsInitobj()293     ALWAYS_INLINE inline bool IsInitobj() const
294     {
295         return (flags_ & IS_INITOBJ) != 0;
296     }
297 
SetInitobj()298     ALWAYS_INLINE inline void SetInitobj()
299     {
300         flags_ = flags_ | IS_INITOBJ;
301     }
302 
GetMethodOffset()303     ALWAYS_INLINE static inline constexpr uint32_t GetMethodOffset()
304     {
305         return MEMBER_OFFSET(Frame, method_);
306     }
307 
GetPrevFrameOffset()308     ALWAYS_INLINE static inline constexpr uint32_t GetPrevFrameOffset()
309     {
310         return MEMBER_OFFSET(Frame, prev_);
311     }
312 
GetNumVregsOffset()313     ALWAYS_INLINE static inline constexpr uint32_t GetNumVregsOffset()
314     {
315         return MEMBER_OFFSET(Frame, nregs_);
316     }
317 
GetVregsOffset()318     ALWAYS_INLINE static inline constexpr uint32_t GetVregsOffset()
319     {
320         return MEMBER_OFFSET(Frame, vregs_);
321     }
322 
GetAccOffset()323     ALWAYS_INLINE static inline constexpr uint32_t GetAccOffset()
324     {
325         return MEMBER_OFFSET(Frame, acc_);
326     }
327 
GetData()328     ALWAYS_INLINE inline void *GetData()
329     {
330         return data_;
331     }
332 
SetData(void * data)333     ALWAYS_INLINE inline void SetData(void *data)
334     {
335         data_ = data;
336     }
337 
338     ~Frame() = default;
339 
340     DEFAULT_COPY_SEMANTIC(Frame);
341     DEFAULT_MOVE_SEMANTIC(Frame);
342 
343 private:
344     Frame *prev_;
345     Method *method_;
346     uint32_t nregs_;
347     uint32_t num_actual_args_;
348     uint32_t bc_offset_;
349     size_t flags_;
350 
351     // It is some language-specific data. Now it is used for JS constant_pool.
352     // 'void' because of it can be used for other purposes
353     void *data_ {nullptr};
354     VRegister acc_;
355     BytecodeInstruction next_inst_;
356     const uint8_t *inst_;
357 
358     __extension__ VRegister vregs_[0];  // NOLINT(modernize-avoid-c-arrays)
359 };
360 
361 }  // namespace panda
362 
363 #endif  // PANDA_RUNTIME_INTERPRETER_FRAME_H_
364