1 /** 2 * Copyright (c) 2021-2022 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 #ifndef PANDA_INTERPRETER_STATE_H_ 16 #define PANDA_INTERPRETER_STATE_H_ 17 18 #include "libpandafile/bytecode_instruction-inl.h" 19 #include "runtime/interpreter/acc_vregister.h" 20 #include "runtime/interpreter/acc_vregister-inl.h" 21 #include "runtime/interpreter/frame.h" 22 23 #ifdef PANDA_ENABLE_GLOBAL_REGISTER_VARIABLES 24 #include "arch/global_regs.h" 25 #endif 26 27 namespace panda::interpreter { 28 29 template <class T> 30 class StateIface { 31 public: StateIface(Frame * frame)32 ALWAYS_INLINE inline explicit StateIface(Frame *frame) : acc_(frame->GetAcc()) {} 33 GetInst()34 ALWAYS_INLINE inline BytecodeInstruction GetInst() const 35 { 36 return static_cast<const T *>(this)->GetInst(); 37 } 38 SetInst(BytecodeInstruction inst)39 ALWAYS_INLINE inline void SetInst(BytecodeInstruction inst) 40 { 41 static_cast<T *>(this)->SetInst(inst); 42 } 43 GetFrame()44 ALWAYS_INLINE inline Frame *GetFrame() const 45 { 46 return static_cast<const T *>(this)->GetFrame(); 47 } 48 SetFrame(Frame * frame)49 ALWAYS_INLINE inline void SetFrame(Frame *frame) 50 { 51 static_cast<T *>(this)->SetFrame(frame); 52 } 53 GetThread()54 ALWAYS_INLINE inline ManagedThread *GetThread() const 55 { 56 return static_cast<const T *>(this)->GetThread(); 57 } 58 SetThread(ManagedThread * thread)59 ALWAYS_INLINE inline void SetThread(ManagedThread *thread) 60 { 61 static_cast<T *>(this)->SetThread(thread); 62 } 63 SaveState()64 ALWAYS_INLINE inline void SaveState() 65 { 66 static_cast<T *>(this)->SaveState(); 67 } 68 RestoreState()69 ALWAYS_INLINE inline void RestoreState() 70 { 71 static_cast<T *>(this)->RestoreState(); 72 } 73 GetAcc()74 ALWAYS_INLINE inline AccVRegisterT &GetAcc() 75 { 76 return acc_; 77 } 78 GetAcc()79 ALWAYS_INLINE inline const AccVRegisterT &GetAcc() const 80 { 81 return acc_; 82 } 83 84 private: 85 AccVRegisterT acc_; 86 }; 87 88 #ifdef PANDA_ENABLE_GLOBAL_REGISTER_VARIABLES 89 90 class State : public StateIface<State> { 91 public: State(ManagedThread * thread,const uint8_t * pc,Frame * frame)92 ALWAYS_INLINE inline State(ManagedThread *thread, const uint8_t *pc, Frame *frame) : StateIface(frame) 93 { 94 SetInst(BytecodeInstruction(pc)); 95 SetFrame(frame); 96 SetThread(thread); 97 } 98 UpdateState(const uint8_t * pc,Frame * frame)99 ALWAYS_INLINE inline void UpdateState(const uint8_t *pc, Frame *frame) 100 { 101 SetInst(BytecodeInstruction(pc)); 102 SetFrame(frame); 103 } 104 GetInst()105 ALWAYS_INLINE inline BytecodeInstruction GetInst() const 106 { 107 return BytecodeInstruction(arch::regs::GetPc()); 108 } 109 SetInst(BytecodeInstruction inst)110 ALWAYS_INLINE inline void SetInst(BytecodeInstruction inst) 111 { 112 arch::regs::SetPc(inst.GetAddress()); 113 } 114 GetFrame()115 ALWAYS_INLINE inline Frame *GetFrame() const 116 { 117 return arch::regs::GetFrame(); 118 } 119 SetFrame(Frame * frame)120 ALWAYS_INLINE inline void SetFrame(Frame *frame) 121 { 122 arch::regs::SetFrame(frame); 123 arch::regs::SetMirrorFp( 124 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(frame) + Frame::GetVregsOffset() + frame->GetSize())); 125 } 126 GetDispatchTable()127 ALWAYS_INLINE inline const void *const *GetDispatchTable() const 128 { 129 return arch::regs::GetDispatchTable(); 130 } 131 SetDispatchTable(const void * const * dispatch_table)132 ALWAYS_INLINE inline void SetDispatchTable(const void *const *dispatch_table) 133 { 134 return arch::regs::SetDispatchTable(dispatch_table); 135 } 136 GetThread()137 ALWAYS_INLINE inline ManagedThread *GetThread() const 138 { 139 return arch::regs::GetThread(); 140 } 141 SetThread(ManagedThread * thread)142 ALWAYS_INLINE inline void SetThread(ManagedThread *thread) 143 { 144 arch::regs::SetThread(thread); 145 } 146 SaveState()147 ALWAYS_INLINE inline void SaveState() 148 { 149 inst_spill_ = GetInst(); 150 acc_spill_ = GetAcc(); 151 fp_spill_ = arch::regs::GetFp(); 152 m_fp_spill_ = arch::regs::GetMirrorFp(); 153 thread_spill_ = GetThread(); 154 } 155 RestoreState()156 ALWAYS_INLINE inline void RestoreState() 157 { 158 SetInst(inst_spill_); 159 GetAcc() = acc_spill_; 160 arch::regs::SetFp(fp_spill_); 161 arch::regs::SetMirrorFp(m_fp_spill_); 162 SetThread(thread_spill_); 163 } 164 165 private: 166 BytecodeInstruction inst_spill_; 167 void *fp_spill_ {nullptr}; 168 void *m_fp_spill_ {nullptr}; 169 ManagedThread *thread_spill_ {nullptr}; 170 AccVRegister acc_spill_; 171 }; 172 173 #else 174 175 class State : public StateIface<State> { 176 public: State(ManagedThread * thread,const uint8_t * pc,Frame * frame)177 ALWAYS_INLINE inline State(ManagedThread *thread, const uint8_t *pc, Frame *frame) : StateIface(frame) 178 { 179 SetInst(BytecodeInstruction(pc)); 180 SetFrame(frame); 181 SetThread(thread); 182 } 183 UpdateState(const uint8_t * pc,Frame * frame)184 ALWAYS_INLINE inline void UpdateState(const uint8_t *pc, Frame *frame) 185 { 186 SetInst(BytecodeInstruction(pc)); 187 SetFrame(frame); 188 } 189 GetInst()190 ALWAYS_INLINE inline BytecodeInstruction GetInst() const 191 { 192 return inst_; 193 } 194 SetInst(BytecodeInstruction inst)195 ALWAYS_INLINE inline void SetInst(BytecodeInstruction inst) 196 { 197 inst_ = inst; 198 } 199 GetFrame()200 ALWAYS_INLINE inline Frame *GetFrame() const 201 { 202 return frame_; 203 } 204 SetFrame(Frame * frame)205 ALWAYS_INLINE inline void SetFrame(Frame *frame) 206 { 207 frame_ = frame; 208 } 209 GetDispatchTable()210 ALWAYS_INLINE inline const void *const *GetDispatchTable() const 211 { 212 return nullptr; 213 } 214 GetThread()215 ALWAYS_INLINE inline ManagedThread *GetThread() const 216 { 217 return thread_; 218 } 219 SetThread(ManagedThread * thread)220 ALWAYS_INLINE inline void SetThread(ManagedThread *thread) 221 { 222 thread_ = thread; 223 } 224 SetDispatchTable(const void * const * dispatch_table)225 void SetDispatchTable([[maybe_unused]] const void *const *dispatch_table) {} 226 SaveState()227 void SaveState() {} 228 RestoreState()229 void RestoreState() {} 230 231 private: 232 BytecodeInstruction inst_; 233 Frame *frame_ {nullptr}; 234 ManagedThread *thread_ {nullptr}; 235 }; 236 237 #endif // PANDA_ENABLE_GLOBAL_REGISTER_VARIABLES 238 239 } // namespace panda::interpreter 240 241 #endif // PANDA_INTERPRETER_VREGISTER_H_ 242