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