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 #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 ark::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,const void * const * dispatchTable)92 ALWAYS_INLINE inline State(ManagedThread *thread, const uint8_t *pc, Frame *frame, const void *const *dispatchTable) 93 : StateIface(frame) 94 { 95 SetInst(BytecodeInstruction(pc)); 96 SetFrame(frame); 97 SetThread(thread); 98 SetDispatchTable(dispatchTable); 99 } 100 UpdateState(const uint8_t * pc,Frame * frame)101 ALWAYS_INLINE inline void UpdateState(const uint8_t *pc, Frame *frame) 102 { 103 SetInst(BytecodeInstruction(pc)); 104 SetFrame(frame); 105 } 106 GetInst()107 ALWAYS_INLINE inline BytecodeInstruction GetInst() const 108 { 109 return BytecodeInstruction(arch::regs::GetPc()); 110 } 111 SetInst(BytecodeInstruction inst)112 ALWAYS_INLINE inline void SetInst(BytecodeInstruction inst) 113 { 114 arch::regs::SetPc(inst.GetAddress()); 115 } 116 GetFrame()117 ALWAYS_INLINE inline Frame *GetFrame() const 118 { 119 return arch::regs::GetFrame(); 120 } 121 SetFrame(Frame * frame)122 ALWAYS_INLINE inline void SetFrame(Frame *frame) 123 { 124 arch::regs::SetFrame(frame); 125 arch::regs::SetMirrorFp( 126 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(frame) + Frame::GetVregsOffset() + frame->GetSize())); 127 } 128 GetDispatchTable()129 ALWAYS_INLINE inline const void *const *GetDispatchTable() const 130 { 131 return arch::regs::GetDispatchTable(); 132 } 133 SetDispatchTable(const void * const * dispatchTable)134 ALWAYS_INLINE inline void SetDispatchTable(const void *const *dispatchTable) 135 { 136 return arch::regs::SetDispatchTable(dispatchTable); 137 } 138 GetThread()139 ALWAYS_INLINE inline ManagedThread *GetThread() const 140 { 141 return arch::regs::GetThread(); 142 } 143 SetThread(ManagedThread * thread)144 ALWAYS_INLINE inline void SetThread(ManagedThread *thread) 145 { 146 arch::regs::SetThread(thread); 147 } 148 SaveState()149 ALWAYS_INLINE inline void SaveState() 150 { 151 instSpill_ = GetInst(); 152 accSpill_ = GetAcc(); 153 fpSpill_ = arch::regs::GetFp(); 154 mFpSpill_ = arch::regs::GetMirrorFp(); 155 threadSpill_ = GetThread(); 156 } 157 RestoreState()158 ALWAYS_INLINE inline void RestoreState() 159 { 160 SetInst(instSpill_); 161 GetAcc() = accSpill_; 162 arch::regs::SetFp(fpSpill_); 163 arch::regs::SetMirrorFp(mFpSpill_); 164 SetThread(threadSpill_); 165 } 166 167 private: 168 BytecodeInstruction instSpill_; 169 void *fpSpill_ {nullptr}; 170 void *mFpSpill_ {nullptr}; 171 ManagedThread *threadSpill_ {nullptr}; 172 AccVRegister accSpill_; 173 }; 174 175 #else 176 177 class State : public StateIface<State> { 178 public: State(ManagedThread * thread,const uint8_t * pc,Frame * frame,const void * const * dispatchTable)179 ALWAYS_INLINE inline State(ManagedThread *thread, const uint8_t *pc, Frame *frame, const void *const *dispatchTable) 180 : StateIface(frame) 181 { 182 SetInst(BytecodeInstruction(pc)); 183 SetFrame(frame); 184 SetThread(thread); 185 SetDispatchTable(dispatchTable); 186 } 187 UpdateState(const uint8_t * pc,Frame * frame)188 ALWAYS_INLINE inline void UpdateState(const uint8_t *pc, Frame *frame) 189 { 190 SetInst(BytecodeInstruction(pc)); 191 SetFrame(frame); 192 } 193 GetInst()194 ALWAYS_INLINE inline BytecodeInstruction GetInst() const 195 { 196 return inst_; 197 } 198 SetInst(BytecodeInstruction inst)199 ALWAYS_INLINE inline void SetInst(BytecodeInstruction inst) 200 { 201 inst_ = inst; 202 } 203 GetFrame()204 ALWAYS_INLINE inline Frame *GetFrame() const 205 { 206 return frame_; 207 } 208 SetFrame(Frame * frame)209 ALWAYS_INLINE inline void SetFrame(Frame *frame) 210 { 211 frame_ = frame; 212 } 213 GetDispatchTable()214 ALWAYS_INLINE inline const void *const *GetDispatchTable() const 215 { 216 return dispatchTable_; 217 } 218 GetThread()219 ALWAYS_INLINE inline ManagedThread *GetThread() const 220 { 221 return thread_; 222 } 223 SetThread(ManagedThread * thread)224 ALWAYS_INLINE inline void SetThread(ManagedThread *thread) 225 { 226 thread_ = thread; 227 } 228 SetDispatchTable(const void * const * dispatchTable)229 void SetDispatchTable(const void *const *dispatchTable) 230 { 231 dispatchTable_ = dispatchTable; 232 } 233 SaveState()234 void SaveState() {} 235 RestoreState()236 void RestoreState() {} 237 238 private: 239 BytecodeInstruction inst_; 240 Frame *frame_ {nullptr}; 241 ManagedThread *thread_ {nullptr}; 242 const void *const *dispatchTable_ {nullptr}; 243 }; 244 245 #endif // PANDA_ENABLE_GLOBAL_REGISTER_VARIABLES 246 247 } // namespace ark::interpreter 248 249 #endif // PANDA_INTERPRETER_VREGISTER_H_ 250