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 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 panda::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), label_back_(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(label_back_)) { 52 label_back_ = encoder->CreateLabel(); 53 } 54 encoder->BindLabel(label_back_); 55 } 56 CreateBackLabel(Encoder * encoder)57 void CreateBackLabel(Encoder *encoder) 58 { 59 label_back_ = encoder->CreateLabel(); 60 } 61 GetBackLabel()62 LabelHolder::LabelId GetBackLabel() 63 { 64 return label_back_; 65 } 66 67 void Generate(Codegen *codegen); 68 69 virtual void GenerateImpl(Codegen *codegen) = 0; 70 71 private: 72 LabelHolder::LabelId label_ {}; 73 LabelHolder::LabelId label_back_ {}; 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 GenerateDeoptimize(Codegen *codegen); 120 bool GenerateByEntry(Codegen *codegen); 121 bool GenerateCreateObject(Codegen *codegen); 122 123 private: 124 EntrypointId entrypoint_ {EntrypointId::COUNT}; 125 }; 126 127 class SlowPathImplicitNullCheck : public SlowPathEntrypoint { 128 public: 129 using SlowPathEntrypoint::SlowPathEntrypoint; 130 131 void GenerateImpl(Codegen *codegen) override; 132 }; 133 134 class SlowPathShared : public SlowPathEntrypoint { 135 public: 136 using SlowPathEntrypoint::SlowPathEntrypoint; 137 138 void GenerateImpl(Codegen *codegen) override; SetTmpReg(Reg reg)139 void SetTmpReg(Reg reg) 140 { 141 tmp_reg_ = reg; 142 } GetTmpReg()143 Reg GetTmpReg() const 144 { 145 return tmp_reg_; 146 } 147 148 private: 149 Reg tmp_reg_ {INVALID_REGISTER}; 150 }; 151 152 class SlowPathResolveStringAot : public SlowPathEntrypoint { 153 public: 154 using SlowPathEntrypoint::SlowPathEntrypoint; 155 156 void GenerateImpl(Codegen *codegen) override; 157 SetDstReg(Reg reg)158 void SetDstReg(Reg reg) 159 { 160 dst_reg_ = reg; 161 } 162 SetAddrReg(Reg reg)163 void SetAddrReg(Reg reg) 164 { 165 addr_reg_ = reg; 166 } 167 SetStringId(uint32_t string_id)168 void SetStringId(uint32_t string_id) 169 { 170 string_id_ = string_id; 171 } 172 SetMethod(void * method)173 void SetMethod(void *method) 174 { 175 method_ = method; 176 } 177 178 private: 179 Reg dst_reg_ {INVALID_REGISTER}; 180 Reg addr_reg_ {INVALID_REGISTER}; 181 uint32_t string_id_ {0}; 182 void *method_ {nullptr}; 183 }; 184 185 class SlowPathCheck : public SlowPathEntrypoint { 186 public: 187 using SlowPathEntrypoint::SlowPathEntrypoint; 188 }; 189 190 class SlowPathCheckCast : public SlowPathEntrypoint { 191 public: 192 using SlowPathEntrypoint::SlowPathEntrypoint; 193 void GenerateImpl(Codegen *codegen) override; SetClassReg(Reg reg)194 void SetClassReg(Reg reg) 195 { 196 class_reg_ = reg; 197 } 198 199 private: 200 Reg class_reg_ {INVALID_REGISTER}; 201 }; 202 203 class SlowPathAbstract : public SlowPathEntrypoint { 204 public: 205 using SlowPathEntrypoint::SlowPathEntrypoint; 206 void GenerateImpl(Codegen *codegen) override; SetMethodReg(Reg reg)207 void SetMethodReg(Reg reg) 208 { 209 method_reg_ = reg; 210 } 211 212 private: 213 Reg method_reg_ {INVALID_REGISTER}; 214 }; 215 216 class SlowPathRefCheck : public SlowPathEntrypoint { 217 public: 218 using SlowPathEntrypoint::SlowPathEntrypoint; 219 220 void GenerateImpl(Codegen *codegen) override; 221 SetRegs(Reg array_reg,Reg ref_reg)222 void SetRegs(Reg array_reg, Reg ref_reg) 223 { 224 array_reg_ = array_reg; 225 ref_reg_ = ref_reg; 226 } 227 228 private: 229 Reg array_reg_ {INVALID_REGISTER}; 230 Reg ref_reg_ {INVALID_REGISTER}; 231 }; 232 233 class SlowPathUnresolved : public SlowPathEntrypoint { 234 public: 235 using SlowPathEntrypoint::SlowPathEntrypoint; 236 237 void GenerateImpl(Codegen *codegen) override; 238 SetUnresolvedType(void * method,uint32_t type_id)239 void SetUnresolvedType(void *method, uint32_t type_id) 240 { 241 method_ = method; 242 type_id_ = type_id; 243 } 244 SetSlotAddr(uintptr_t addr)245 void SetSlotAddr(uintptr_t addr) 246 { 247 slot_addr_ = addr; 248 } 249 SetDstReg(Reg dst_reg)250 void SetDstReg(Reg dst_reg) 251 { 252 dst_reg_ = dst_reg; 253 } 254 SetArgReg(Reg arg_reg)255 void SetArgReg(Reg arg_reg) 256 { 257 arg_reg_ = arg_reg; 258 } 259 260 private: 261 Reg dst_reg_ {INVALID_REGISTER}; 262 Reg arg_reg_ {INVALID_REGISTER}; 263 void *method_ {nullptr}; 264 uint32_t type_id_ {0}; 265 uintptr_t slot_addr_ {0}; 266 }; 267 } // namespace panda::compiler 268 269 #endif // PANDA_SLOW_PATH_H 270