• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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