1 /*
2 * Copyright (c) 2023 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 #include "ecmascript/compiler/gate.h"
17 #include "ecmascript/compiler/share_gate_meta_data.h"
18 #include "ecmascript/compiler/gate_meta_data_builder.h"
19
20 namespace panda::ecmascript::kungfu {
21
Str(OpCode opcode)22 std::string GateMetaData::Str(OpCode opcode)
23 {
24 const std::map<OpCode, const char *> strMap = {
25 #define GATE_NAME_MAP(NAME, OP, R, S, D, V) { OpCode::OP, #OP },
26 IMMUTABLE_META_DATA_CACHE_LIST(GATE_NAME_MAP)
27 GATE_META_DATA_LIST_WITH_BOOL(GATE_NAME_MAP)
28 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(GATE_NAME_MAP)
29 GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP)
30 GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP)
31 GATE_META_DATA_LIST_WITH_PC_OFFSET(GATE_NAME_MAP)
32 GATE_META_DATA_LIST_FOR_CALL(GATE_NAME_MAP)
33 GATE_META_DATA_LIST_FOR_NEW(GATE_NAME_MAP)
34 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(GATE_NAME_MAP)
35 #undef GATE_NAME_MAP
36 #define GATE_NAME_MAP(OP) { OpCode::OP, #OP },
37 GATE_OPCODE_LIST(GATE_NAME_MAP)
38 #undef GATE_NAME_MAP
39 };
40 if (strMap.count(opcode) > 0) {
41 return strMap.at(opcode);
42 }
43 return "OP-" + std::to_string(static_cast<uint8_t>(opcode));
44 }
45
IsRoot() const46 bool GateMetaData::IsRoot() const
47 {
48 switch (opcode_) {
49 case OpCode::CIRCUIT_ROOT:
50 case OpCode::DEPEND_ENTRY:
51 case OpCode::ARG_LIST:
52 case OpCode::STATE_ENTRY:
53 case OpCode::RETURN_LIST:
54 return true;
55 default:
56 return false;
57 }
58 }
59
IsProlog() const60 bool GateMetaData::IsProlog() const
61 {
62 return (opcode_ == OpCode::ARG || opcode_ == OpCode::INITVREG);
63 }
64
IsFixed() const65 bool GateMetaData::IsFixed() const
66 {
67 switch (opcode_) {
68 case OpCode::VALUE_SELECTOR:
69 case OpCode::DEPEND_SELECTOR:
70 case OpCode::DEPEND_RELAY:
71 case OpCode::LOOP_EXIT_DEPEND:
72 case OpCode::LOOP_EXIT_VALUE:
73 return true;
74 default:
75 return false;
76 }
77 }
78
IsSchedulable() const79 bool GateMetaData::IsSchedulable() const
80 {
81 ASSERT(!IsNop());
82 #ifndef NDEBUG
83 if (GetStateCount() == 0) {
84 ASSERT(!IsFixed());
85 }
86 #endif
87 return (!IsProlog()) && (!IsRoot()) && (GetStateCount() == 0);
88 }
89
IsState() const90 bool GateMetaData::IsState() const
91 {
92 ASSERT(!IsNop());
93 #ifndef NDEBUG
94 if (GetStateCount() > 0) {
95 ASSERT(!IsProlog());
96 ASSERT(!IsRoot());
97 }
98 #endif
99 return (!IsVirtualState()) && (!IsFixed()) && (GetStateCount() > 0);
100 }
101
IsGeneralState() const102 bool GateMetaData::IsGeneralState() const
103 {
104 switch (opcode_) {
105 case OpCode::IF_BRANCH:
106 case OpCode::SWITCH_BRANCH:
107 case OpCode::IF_TRUE:
108 case OpCode::IF_FALSE:
109 case OpCode::IF_SUCCESS:
110 case OpCode::IF_EXCEPTION:
111 case OpCode::SWITCH_CASE:
112 case OpCode::DEFAULT_CASE:
113 case OpCode::MERGE:
114 case OpCode::LOOP_BEGIN:
115 case OpCode::LOOP_BACK:
116 case OpCode::LOOP_EXIT:
117 case OpCode::ORDINARY_BLOCK:
118 case OpCode::STATE_ENTRY:
119 case OpCode::DEOPT_CHECK:
120 case OpCode::RETURN:
121 case OpCode::RETURN_VOID:
122 return true;
123 default:
124 return false;
125 }
126 }
127
IsTerminalState() const128 bool GateMetaData::IsTerminalState() const
129 {
130 switch (opcode_) {
131 case OpCode::RETURN:
132 case OpCode::THROW:
133 case OpCode::RETURN_VOID:
134 case OpCode::GET_EXCEPTION:
135 case OpCode::STATE_SPLIT:
136 return true;
137 default:
138 return false;
139 }
140 }
141
IsVirtualState() const142 bool GateMetaData::IsVirtualState() const
143 {
144 switch (opcode_) {
145 case OpCode::GET_EXCEPTION:
146 case OpCode::STATE_SPLIT:
147 return true;
148 default:
149 return false;
150 }
151 }
152
IsCFGMerge() const153 bool GateMetaData::IsCFGMerge() const
154 {
155 return (opcode_ == OpCode::MERGE) || (opcode_ == OpCode::LOOP_BEGIN);
156 }
157
IsControlCase() const158 bool GateMetaData::IsControlCase() const
159 {
160 ASSERT(HasFlag(GateFlags::CONTROL));
161 // should add relay
162 switch (opcode_) {
163 case OpCode::IF_BRANCH:
164 case OpCode::SWITCH_BRANCH:
165 case OpCode::IF_TRUE:
166 case OpCode::IF_FALSE:
167 case OpCode::SWITCH_CASE:
168 case OpCode::DEFAULT_CASE:
169 return true;
170 default:
171 return false;
172 }
173 }
174
IsIfOrSwitchRelated() const175 bool GateMetaData::IsIfOrSwitchRelated() const
176 {
177 switch (opcode_) {
178 case OpCode::IF_TRUE:
179 case OpCode::IF_FALSE:
180 case OpCode::SWITCH_CASE:
181 case OpCode::DEFAULT_CASE:
182 case OpCode::IF_SUCCESS:
183 case OpCode::IF_EXCEPTION:
184 return true;
185 default:
186 return false;
187 }
188 }
189
IsLoopHead() const190 bool GateMetaData::IsLoopHead() const
191 {
192 return (opcode_ == OpCode::LOOP_BEGIN);
193 }
194
IsNop() const195 bool GateMetaData::IsNop() const
196 {
197 return (opcode_ == OpCode::NOP || opcode_ == OpCode::DEAD);
198 }
199
IsDead() const200 bool GateMetaData::IsDead() const
201 {
202 return opcode_ == OpCode::DEAD;
203 }
204
IsConstant() const205 bool GateMetaData::IsConstant() const
206 {
207 return (opcode_ == OpCode::CONSTANT);
208 }
209
IsDependSelector() const210 bool GateMetaData::IsDependSelector() const
211 {
212 return (opcode_ == OpCode::DEPEND_SELECTOR);
213 }
214
GateMetaBuilder(Chunk* chunk)215 GateMetaBuilder::GateMetaBuilder(Chunk* chunk)
216 : cache_(), chunk_(chunk) {}
217
218 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
219 const GateMetaData* GateMetaBuilder::NAME() \
220 { \
221 return &cache_.cached##NAME##_; \
222 }
223 IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
224 #undef DECLARE_GATE_META
225
226 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
227 const GateMetaData* GateMetaBuilder::NAME(bool value) \
228 { \
229 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, value); \
230 return meta; \
231 }
232 GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)
233 #undef DECLARE_GATE_META
234
235 #define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V) \
236 const GateMetaData* GateMetaBuilder::NAME(size_t value, bool flag) \
237 { \
238 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, flag); \
239 return meta; \
240 }
241 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN)
242 #undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN
243
244 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
245 const GateMetaData* GateMetaBuilder::NAME(size_t value) \
246 { \
247 switch (value) { \
248 case GateMetaDataChache::ONE_VALUE: \
249 return &cache_.cached##NAME##1_; \
250 case GateMetaDataChache::TWO_VALUE: \
251 return &cache_.cached##NAME##2_; \
252 case GateMetaDataChache::THREE_VALUE: \
253 return &cache_.cached##NAME##3_; \
254 case GateMetaDataChache::FOUR_VALUE: \
255 return &cache_.cached##NAME##4_; \
256 case GateMetaDataChache::FIVE_VALUE: \
257 return &cache_.cached##NAME##5_; \
258 default: \
259 break; \
260 } \
261 auto meta = new (chunk_) GateMetaData(OpCode::OP, R, S, D, V); \
262 meta->SetKind(GateMetaData::Kind::MUTABLE_WITH_SIZE); \
263 return meta; \
264 }
265 GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
266 #undef DECLARE_GATE_META
267
268 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
269 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
270 { \
271 switch (value) { \
272 case GateMetaDataChache::ONE_VALUE: \
273 return &cache_.cached##NAME##1_; \
274 case GateMetaDataChache::TWO_VALUE: \
275 return &cache_.cached##NAME##2_; \
276 case GateMetaDataChache::THREE_VALUE: \
277 return &cache_.cached##NAME##3_; \
278 case GateMetaDataChache::FOUR_VALUE: \
279 return &cache_.cached##NAME##4_; \
280 case GateMetaDataChache::FIVE_VALUE: \
281 return &cache_.cached##NAME##5_; \
282 default: \
283 break; \
284 } \
285 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
286 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
287 return meta; \
288 }
289 GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_META)
290 #undef DECLARE_GATE_META
291
292 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
293 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
294 { \
295 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
296 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
297 return meta; \
298 }
299 GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_META)
300 #undef DECLARE_GATE_META
301
302 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
303 const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset) \
304 { \
305 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, value, pcOffset); \
306 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
307 return meta; \
308 }
309 GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
310 #undef DECLARE_GATE_META
311
312 #define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V) \
313 const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset, bool noGC) \
314 { \
315 auto meta = new (chunk_) TypedCallMetaData(OpCode::OP, R, S, D, value, pcOffset, noGC); \
316 meta->SetKind(GateMetaData::Kind::TYPED_CALL); \
317 return meta; \
318 }
319 GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL)
320 #undef DECLARE_GATE_META_FOR_CALL
321
322 #define DECLARE_GATE_META_FOR_NEW(NAME, OP, R, S, D, V) \
323 const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset, \
324 bool isFastCall) \
325 { \
326 auto meta = new (chunk_) NewConstructMetaData(OpCode::OP, R, S, D, value, \
327 pcOffset, isFastCall); \
328 meta->SetKind(GateMetaData::Kind::CALL_NEW); \
329 return meta; \
330 }
331 GATE_META_DATA_LIST_FOR_NEW(DECLARE_GATE_META_FOR_NEW)
332 #undef DECLARE_GATE_META_FOR_NEW
333
334 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
335 const GateMetaData* GateMetaBuilder::NAME(uint64_t pcOffset) const \
336 { \
337 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, pcOffset); \
338 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
339 return meta; \
340 }
341 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
342 #undef DECLARE_GATE_META
343
Arg(uint64_t value)344 const GateMetaData* GateMetaBuilder::Arg(uint64_t value)
345 {
346 switch (value) {
347 #define DECLARE_CACHED_VALUE_CASE(VALUE) \
348 case VALUE: { \
349 return &cache_.cachedArg##VALUE##_; \
350 }
351 CACHED_ARG_LIST(DECLARE_CACHED_VALUE_CASE)
352 #undef DECLARE_CACHED_VALUE_CASE
353 default:
354 break;
355 }
356
357 auto meta = new (chunk_) OneParameterMetaData(OpCode::ARG, GateFlags::HAS_ROOT, 0, 0, 0, value);
358 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER);
359 return meta;
360 }
361
InitVreg(uint64_t value)362 const GateMetaData* GateMetaBuilder::InitVreg(uint64_t value)
363 {
364 auto meta = new (chunk_) OneParameterMetaData(OpCode::INITVREG, GateFlags::HAS_ROOT, 0, 0, 0, value);
365 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER);
366 return meta;
367 }
368 } // namespace panda::ecmascript::kungfu
369