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 PANDA_SLOW_PATH_H 17 #define PANDA_SLOW_PATH_H 18 19 #include "optimizer/ir/graph.h" 20 #include "optimizer/code_generator/encode.h" 21 22 namespace ark::compiler { 23 class Codegen; 24 25 class SlowPathBase { 26 public: 27 using EntrypointId = RuntimeInterface::EntrypointId; 28 SlowPathBase(LabelHolder::LabelId label)29 explicit SlowPathBase(LabelHolder::LabelId label) : SlowPathBase(label, nullptr) {} SlowPathBase(LabelHolder::LabelId label,Inst * inst)30 SlowPathBase(LabelHolder::LabelId label, Inst *inst) 31 : label_(label), labelBack_(LabelHolder::INVALID_LABEL), inst_(inst) 32 { 33 } 34 virtual ~SlowPathBase() = default; 35 36 NO_COPY_SEMANTIC(SlowPathBase); 37 NO_MOVE_SEMANTIC(SlowPathBase); 38 GetInst()39 Inst *GetInst() const 40 { 41 return inst_; 42 } 43 GetLabel()44 auto &GetLabel() const 45 { 46 return label_; 47 } 48 BindBackLabel(Encoder * encoder)49 void BindBackLabel(Encoder *encoder) 50 { 51 if (!encoder->IsLabelValid(labelBack_)) { 52 labelBack_ = encoder->CreateLabel(); 53 } 54 encoder->BindLabel(labelBack_); 55 } 56 CreateBackLabel(Encoder * encoder)57 void CreateBackLabel(Encoder *encoder) 58 { 59 labelBack_ = encoder->CreateLabel(); 60 } 61 GetBackLabel()62 LabelHolder::LabelId GetBackLabel() 63 { 64 return labelBack_; 65 } 66 67 void Generate(Codegen *codegen); 68 69 virtual void GenerateImpl(Codegen *codegen) = 0; 70 71 private: 72 LabelHolder::LabelId label_ {LabelHolder::INVALID_LABEL}; 73 LabelHolder::LabelId labelBack_ {LabelHolder::INVALID_LABEL}; 74 Inst *inst_ {nullptr}; 75 76 #ifndef NDEBUG 77 // Intended to check that slow path is generated only once. 78 bool generated_ {false}; 79 #endif 80 }; 81 82 class SlowPathIntrinsic : public SlowPathBase { 83 public: 84 using SlowPathBase::SlowPathBase; 85 SlowPathIntrinsic(LabelHolder::LabelId label,Inst * inst)86 SlowPathIntrinsic(LabelHolder::LabelId label, Inst *inst) : SlowPathBase(label, inst) {} 87 ~SlowPathIntrinsic() override = default; 88 89 NO_COPY_SEMANTIC(SlowPathIntrinsic); 90 NO_MOVE_SEMANTIC(SlowPathIntrinsic); 91 92 void GenerateImpl(Codegen *codegen) override; 93 }; 94 95 class SlowPathEntrypoint : public SlowPathBase { 96 public: SlowPathEntrypoint(LabelHolder::LabelId label)97 explicit SlowPathEntrypoint(LabelHolder::LabelId label) : SlowPathBase(label) {} SlowPathEntrypoint(LabelHolder::LabelId label,Inst * inst,EntrypointId eid)98 SlowPathEntrypoint(LabelHolder::LabelId label, Inst *inst, EntrypointId eid) 99 : SlowPathBase(label, inst), entrypoint_(eid) 100 { 101 } 102 ~SlowPathEntrypoint() override = default; 103 104 void GenerateImpl(Codegen *codegen) override; 105 GetEntrypoint()106 EntrypointId GetEntrypoint() 107 { 108 return entrypoint_; 109 } 110 111 NO_COPY_SEMANTIC(SlowPathEntrypoint); 112 NO_MOVE_SEMANTIC(SlowPathEntrypoint); 113 114 private: 115 bool GenerateThrowOutOfBoundsException(Codegen *codegen); 116 bool GenerateInitializeClass(Codegen *codegen); 117 bool GenerateIsInstance(Codegen *codegen); 118 bool GenerateCheckCast(Codegen *codegen); 119 bool GenerateByEntry(Codegen *codegen); 120 bool GenerateCreateObject(Codegen *codegen); 121 122 private: 123 EntrypointId entrypoint_ {EntrypointId::COUNT}; 124 }; 125 126 class SlowPathDeoptimize : public SlowPathEntrypoint { 127 public: 128 ~SlowPathDeoptimize() override = default; 129 NO_COPY_SEMANTIC(SlowPathDeoptimize); 130 NO_MOVE_SEMANTIC(SlowPathDeoptimize); 131 SlowPathDeoptimize(LabelHolder::LabelId label,Inst * inst,DeoptimizeType deoptimizeType)132 SlowPathDeoptimize(LabelHolder::LabelId label, Inst *inst, DeoptimizeType deoptimizeType) 133 : SlowPathEntrypoint(label, inst, EntrypointId::DEOPTIMIZE), deoptimizeType_ {deoptimizeType} 134 { 135 } 136 137 void GenerateImpl(Codegen *codegen) override; 138 139 private: 140 DeoptimizeType deoptimizeType_; 141 }; 142 143 class SlowPathImplicitNullCheck : public SlowPathEntrypoint { 144 public: 145 using SlowPathEntrypoint::SlowPathEntrypoint; 146 147 void GenerateImpl(Codegen *codegen) override; 148 }; 149 150 class SlowPathShared : public SlowPathEntrypoint { 151 public: 152 using SlowPathEntrypoint::SlowPathEntrypoint; 153 154 void GenerateImpl(Codegen *codegen) override; SetTmpReg(Reg reg)155 void SetTmpReg(Reg reg) 156 { 157 tmpReg_ = reg; 158 } GetTmpReg()159 Reg GetTmpReg() const 160 { 161 return tmpReg_; 162 } 163 164 private: 165 Reg tmpReg_ {INVALID_REGISTER}; 166 }; 167 168 class SlowPathResolveStringAot : public SlowPathEntrypoint { 169 public: 170 using SlowPathEntrypoint::SlowPathEntrypoint; 171 172 void GenerateImpl(Codegen *codegen) override; 173 SetDstReg(Reg reg)174 void SetDstReg(Reg reg) 175 { 176 dstReg_ = reg; 177 } 178 SetAddrReg(Reg reg)179 void SetAddrReg(Reg reg) 180 { 181 addrReg_ = reg; 182 } 183 SetStringId(uint32_t stringId)184 void SetStringId(uint32_t stringId) 185 { 186 stringId_ = stringId; 187 } 188 SetMethod(void * method)189 void SetMethod(void *method) 190 { 191 method_ = method; 192 } 193 194 private: 195 Reg dstReg_ {INVALID_REGISTER}; 196 Reg addrReg_ {INVALID_REGISTER}; 197 uint32_t stringId_ {0}; 198 void *method_ {nullptr}; 199 }; 200 201 class SlowPathCheck : public SlowPathEntrypoint { 202 public: 203 using SlowPathEntrypoint::SlowPathEntrypoint; 204 }; 205 206 class SlowPathCheckCast : public SlowPathEntrypoint { 207 public: 208 using SlowPathEntrypoint::SlowPathEntrypoint; 209 void GenerateImpl(Codegen *codegen) override; SetClassReg(Reg reg)210 void SetClassReg(Reg reg) 211 { 212 classReg_ = reg; 213 } 214 215 private: 216 Reg classReg_ {INVALID_REGISTER}; 217 }; 218 219 class SlowPathAbstract : public SlowPathEntrypoint { 220 public: 221 using SlowPathEntrypoint::SlowPathEntrypoint; 222 void GenerateImpl(Codegen *codegen) override; SetMethodReg(Reg reg)223 void SetMethodReg(Reg reg) 224 { 225 methodReg_ = reg; 226 } 227 228 private: 229 Reg methodReg_ {INVALID_REGISTER}; 230 }; 231 232 class SlowPathRefCheck : public SlowPathEntrypoint { 233 public: 234 using SlowPathEntrypoint::SlowPathEntrypoint; 235 236 void GenerateImpl(Codegen *codegen) override; 237 SetRegs(Reg arrayReg,Reg refReg)238 void SetRegs(Reg arrayReg, Reg refReg) 239 { 240 arrayReg_ = arrayReg; 241 refReg_ = refReg; 242 } 243 244 private: 245 Reg arrayReg_ {INVALID_REGISTER}; 246 Reg refReg_ {INVALID_REGISTER}; 247 }; 248 249 class SlowPathUnresolved : public SlowPathEntrypoint { 250 public: 251 using SlowPathEntrypoint::SlowPathEntrypoint; 252 253 void GenerateImpl(Codegen *codegen) override; 254 SetUnresolvedType(void * method,uint32_t typeId)255 void SetUnresolvedType(void *method, uint32_t typeId) 256 { 257 method_ = method; 258 typeId_ = typeId; 259 } 260 SetSlotAddr(uintptr_t addr)261 void SetSlotAddr(uintptr_t addr) 262 { 263 slotAddr_ = addr; 264 } 265 SetDstReg(Reg dstReg)266 void SetDstReg(Reg dstReg) 267 { 268 dstReg_ = dstReg; 269 } 270 SetArgReg(Reg argReg)271 void SetArgReg(Reg argReg) 272 { 273 argReg_ = argReg; 274 } 275 276 private: 277 Reg dstReg_ {INVALID_REGISTER}; 278 Reg argReg_ {INVALID_REGISTER}; 279 void *method_ {nullptr}; 280 uint32_t typeId_ {0}; 281 uintptr_t slotAddr_ {0}; 282 }; 283 284 class SlowPathJsCastDoubleToInt32 : public SlowPathBase { 285 public: 286 using SlowPathBase::SlowPathBase; 287 288 ~SlowPathJsCastDoubleToInt32() override = default; 289 290 NO_COPY_SEMANTIC(SlowPathJsCastDoubleToInt32); 291 NO_MOVE_SEMANTIC(SlowPathJsCastDoubleToInt32); 292 SetSrcReg(Reg srcReg)293 void SetSrcReg(Reg srcReg) 294 { 295 srcReg_ = srcReg; 296 } 297 SetDstReg(Reg dstReg)298 void SetDstReg(Reg dstReg) 299 { 300 dstReg_ = dstReg; 301 } 302 303 void GenerateImpl(Codegen *codegen) override; 304 305 private: 306 Reg srcReg_ {INVALID_REGISTER}; 307 Reg dstReg_ {INVALID_REGISTER}; 308 }; 309 310 class SlowPathStringHashCode : public SlowPathEntrypoint { 311 public: 312 using SlowPathEntrypoint::SlowPathEntrypoint; 313 314 ~SlowPathStringHashCode() override = default; 315 316 NO_COPY_SEMANTIC(SlowPathStringHashCode); 317 NO_MOVE_SEMANTIC(SlowPathStringHashCode); 318 SetDstReg(Reg dstReg)319 void SetDstReg(Reg dstReg) 320 { 321 dstReg_ = dstReg; 322 } 323 SetSrcReg(Reg srcReg)324 void SetSrcReg(Reg srcReg) 325 { 326 srcReg_ = srcReg; 327 } 328 329 void GenerateImpl(Codegen *codegen) override; 330 331 private: 332 Reg dstReg_ {INVALID_REGISTER}; 333 Reg srcReg_ {INVALID_REGISTER}; 334 }; 335 336 } // namespace ark::compiler 337 338 #endif // PANDA_SLOW_PATH_H 339