1 /*
2 * Copyright (c) 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 #include "ecmascript/compiler/gate.h"
17 #include "ecmascript/compiler/gate_meta_data.h"
18 #include "ecmascript/compiler/gate_meta_data_builder.h"
19
20 namespace panda::ecmascript::kungfu {
MachineTypeToStr(MachineType machineType)21 std::string MachineTypeToStr(MachineType machineType)
22 {
23 switch (machineType) {
24 case NOVALUE:
25 return "NOVALUE";
26 case ANYVALUE:
27 return "ANYVALUE";
28 case I1:
29 return "I1";
30 case I8:
31 return "I8";
32 case I16:
33 return "I16";
34 case I32:
35 return "I32";
36 case I64:
37 return "I64";
38 case F32:
39 return "F32";
40 case F64:
41 return "F64";
42 default:
43 return "???";
44 }
45 }
46
TypedBinOpToStr(TypedBinOp typedBinOp) const47 std::string GateMetaData::TypedBinOpToStr(TypedBinOp typedBinOp) const
48 {
49 switch (typedBinOp) {
50 case TypedBinOp::TYPED_ADD: {
51 return "Add";
52 }
53 case TypedBinOp::TYPED_SUB: {
54 return "Sub";
55 }
56 case TypedBinOp::TYPED_MUL: {
57 return "Mul";
58 }
59 case TypedBinOp::TYPED_LESS: {
60 return "Less";
61 }
62 case TypedBinOp::TYPED_LESSEQ: {
63 return "LessOrEqual";
64 }
65 case TypedBinOp::TYPED_GREATER: {
66 return "Greater";
67 }
68 case TypedBinOp::TYPED_GREATEREQ: {
69 return "GreaterOrEqual";
70 }
71 case TypedBinOp::TYPED_EQ: {
72 return "Equal";
73 }
74 case TypedBinOp::TYPED_NOTEQ: {
75 return "NotEqual";
76 }
77 case TypedBinOp::TYPED_STRICTEQ: {
78 return "StrictEqual";
79 }
80 case TypedBinOp::TYPED_SHL: {
81 return "Shl";
82 }
83 case TypedBinOp::TYPED_SHR: {
84 return "Shr";
85 }
86 case TypedBinOp::TYPED_ASHR: {
87 return "Ashr";
88 }
89 case TypedBinOp::TYPED_AND: {
90 return "And";
91 }
92 case TypedBinOp::TYPED_OR: {
93 return "Or";
94 }
95 case TypedBinOp::TYPED_XOR: {
96 return "Xor";
97 }
98 case TypedBinOp::TYPED_DIV: {
99 return "Div";
100 }
101 case TypedBinOp::TYPED_EXP: {
102 return "Exp";
103 }
104 default:
105 return "Unknown";
106 }
107 }
108
Str(OpCode opcode)109 std::string GateMetaData::Str(OpCode opcode)
110 {
111 const std::map<OpCode, const char *> strMap = {
112 #define GATE_NAME_MAP(NAME, OP, R, S, D, V) { OpCode::OP, #OP },
113 IMMUTABLE_META_DATA_CACHE_LIST(GATE_NAME_MAP)
114 GATE_META_DATA_LIST_WITH_BOOL(GATE_NAME_MAP)
115 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(GATE_NAME_MAP)
116 GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP)
117 GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP)
118 GATE_META_DATA_LIST_WITH_PC_OFFSET(GATE_NAME_MAP)
119 GATE_META_DATA_LIST_FOR_CALL(GATE_NAME_MAP)
120 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(GATE_NAME_MAP)
121 #undef GATE_NAME_MAP
122 #define GATE_NAME_MAP(OP) { OpCode::OP, #OP },
123 GATE_OPCODE_LIST(GATE_NAME_MAP)
124 #undef GATE_NAME_MAP
125 };
126 if (strMap.count(opcode) > 0) {
127 return strMap.at(opcode);
128 }
129 return "OP-" + std::to_string(static_cast<uint8_t>(opcode));
130 }
131
IsRoot() const132 bool GateMetaData::IsRoot() const
133 {
134 switch (opcode_) {
135 case OpCode::CIRCUIT_ROOT:
136 case OpCode::DEPEND_ENTRY:
137 case OpCode::ARG_LIST:
138 case OpCode::STATE_ENTRY:
139 case OpCode::RETURN_LIST:
140 return true;
141 default:
142 return false;
143 }
144 }
145
IsProlog() const146 bool GateMetaData::IsProlog() const
147 {
148 return (opcode_ == OpCode::ARG);
149 }
150
IsFixed() const151 bool GateMetaData::IsFixed() const
152 {
153 switch (opcode_) {
154 case OpCode::VALUE_SELECTOR:
155 case OpCode::DEPEND_SELECTOR:
156 case OpCode::DEPEND_RELAY:
157 case OpCode::LOOP_EXIT_DEPEND:
158 case OpCode::LOOP_EXIT_VALUE:
159 return true;
160 default:
161 return false;
162 }
163 }
164
IsSchedulable() const165 bool GateMetaData::IsSchedulable() const
166 {
167 ASSERT(!IsNop());
168 #ifndef NDEBUG
169 if (GetStateCount() == 0) {
170 ASSERT(!IsFixed());
171 }
172 #endif
173 return (!IsProlog()) && (!IsRoot()) && (GetStateCount() == 0);
174 }
175
IsState() const176 bool GateMetaData::IsState() const
177 {
178 ASSERT(!IsNop());
179 #ifndef NDEBUG
180 if (GetStateCount() > 0) {
181 ASSERT(!IsProlog());
182 ASSERT(!IsRoot());
183 }
184 #endif
185 return (!IsVirtualState()) && (!IsFixed()) && (GetStateCount() > 0);
186 }
187
IsGeneralState() const188 bool GateMetaData::IsGeneralState() const
189 {
190 switch (opcode_) {
191 case OpCode::IF_BRANCH:
192 case OpCode::SWITCH_BRANCH:
193 case OpCode::IF_TRUE:
194 case OpCode::IF_FALSE:
195 case OpCode::IF_SUCCESS:
196 case OpCode::IF_EXCEPTION:
197 case OpCode::SWITCH_CASE:
198 case OpCode::DEFAULT_CASE:
199 case OpCode::MERGE:
200 case OpCode::LOOP_BEGIN:
201 case OpCode::LOOP_BACK:
202 case OpCode::LOOP_EXIT:
203 case OpCode::ORDINARY_BLOCK:
204 case OpCode::STATE_ENTRY:
205 case OpCode::DEOPT_CHECK:
206 case OpCode::RETURN:
207 case OpCode::RETURN_VOID:
208 return true;
209 default:
210 return false;
211 }
212 }
213
IsTerminalState() const214 bool GateMetaData::IsTerminalState() const
215 {
216 switch (opcode_) {
217 case OpCode::RETURN:
218 case OpCode::THROW:
219 case OpCode::RETURN_VOID:
220 case OpCode::GET_EXCEPTION:
221 case OpCode::STATE_SPLIT:
222 return true;
223 default:
224 return false;
225 }
226 }
227
IsVirtualState() const228 bool GateMetaData::IsVirtualState() const
229 {
230 switch (opcode_) {
231 case OpCode::GET_EXCEPTION:
232 case OpCode::STATE_SPLIT:
233 return true;
234 default:
235 return false;
236 }
237 }
238
IsCFGMerge() const239 bool GateMetaData::IsCFGMerge() const
240 {
241 return (opcode_ == OpCode::MERGE) || (opcode_ == OpCode::LOOP_BEGIN);
242 }
243
IsControlCase() const244 bool GateMetaData::IsControlCase() const
245 {
246 ASSERT(HasFlag(GateFlags::CONTROL));
247 // should add relay
248 switch (opcode_) {
249 case OpCode::IF_BRANCH:
250 case OpCode::SWITCH_BRANCH:
251 case OpCode::IF_TRUE:
252 case OpCode::IF_FALSE:
253 case OpCode::SWITCH_CASE:
254 case OpCode::DEFAULT_CASE:
255 return true;
256 default:
257 return false;
258 }
259 }
260
IsLoopHead() const261 bool GateMetaData::IsLoopHead() const
262 {
263 return (opcode_ == OpCode::LOOP_BEGIN);
264 }
265
IsNop() const266 bool GateMetaData::IsNop() const
267 {
268 return (opcode_ == OpCode::NOP || opcode_ == OpCode::DEAD);
269 }
270
IsConstant() const271 bool GateMetaData::IsConstant() const
272 {
273 return (opcode_ == OpCode::CONSTANT);
274 }
275
IsDependSelector() const276 bool GateMetaData::IsDependSelector() const
277 {
278 return (opcode_ == OpCode::DEPEND_SELECTOR);
279 }
280
IsTypedOperator() const281 bool GateMetaData::IsTypedOperator() const
282 {
283 return (opcode_ == OpCode::TYPED_BINARY_OP) || (opcode_ == OpCode::TYPE_CONVERT) ||
284 (opcode_ == OpCode::TYPED_UNARY_OP);
285 }
286
IsCheckWithTwoIns() const287 bool GateMetaData::IsCheckWithTwoIns() const
288 {
289 return (opcode_ == OpCode::OBJECT_TYPE_CHECK) ||
290 (opcode_ == OpCode::INDEX_CHECK) ||
291 (opcode_ == OpCode::TYPED_CALL_CHECK);
292 }
293
IsCheckWithOneIn() const294 bool GateMetaData::IsCheckWithOneIn() const
295 {
296 return (opcode_ == OpCode::PRIMITIVE_TYPE_CHECK) ||
297 (opcode_ == OpCode::HEAP_OBJECT_CHECK) ||
298 (opcode_ == OpCode::STABLE_ARRAY_CHECK) ||
299 (opcode_ == OpCode::TYPED_ARRAY_CHECK);
300 }
301
GateMetaBuilder(Chunk * chunk)302 GateMetaBuilder::GateMetaBuilder(Chunk* chunk)
303 : cache_(), chunk_(chunk) {}
304
305 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
306 const GateMetaData* GateMetaBuilder::NAME() \
307 { \
308 return &cache_.cached##NAME##_; \
309 }
310 IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
311 #undef DECLARE_GATE_META
312
313 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
314 const GateMetaData* GateMetaBuilder::NAME(bool value) \
315 { \
316 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, value); \
317 return meta; \
318 }
GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)319 GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)
320 #undef DECLARE_GATE_META
321
322 #define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V) \
323 const GateMetaData* GateMetaBuilder::NAME(size_t value, bool flag) \
324 { \
325 auto meta = new (chunk_) BoolMetaData(OpCode::OP, R, S, D, V, flag); \
326 return meta; \
327 }
328 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN)
329 #undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN
330
331 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
332 const GateMetaData* GateMetaBuilder::NAME(size_t value) \
333 { \
334 switch (value) { \
335 case GateMetaDataChache::ONE_VALUE: \
336 return &cache_.cached##NAME##1_; \
337 case GateMetaDataChache::TWO_VALUE: \
338 return &cache_.cached##NAME##2_; \
339 case GateMetaDataChache::THREE_VALUE: \
340 return &cache_.cached##NAME##3_; \
341 case GateMetaDataChache::FOUR_VALUE: \
342 return &cache_.cached##NAME##4_; \
343 case GateMetaDataChache::FIVE_VALUE: \
344 return &cache_.cached##NAME##5_; \
345 default: \
346 break; \
347 } \
348 auto meta = new (chunk_) GateMetaData(OpCode::OP, R, S, D, V); \
349 meta->SetKind(GateMetaData::Kind::MUTABLE_WITH_SIZE); \
350 return meta; \
351 }
352 GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
353 #undef DECLARE_GATE_META
354
355 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
356 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
357 { \
358 switch (value) { \
359 case GateMetaDataChache::ONE_VALUE: \
360 return &cache_.cached##NAME##1_; \
361 case GateMetaDataChache::TWO_VALUE: \
362 return &cache_.cached##NAME##2_; \
363 case GateMetaDataChache::THREE_VALUE: \
364 return &cache_.cached##NAME##3_; \
365 case GateMetaDataChache::FOUR_VALUE: \
366 return &cache_.cached##NAME##4_; \
367 case GateMetaDataChache::FIVE_VALUE: \
368 return &cache_.cached##NAME##5_; \
369 default: \
370 break; \
371 } \
372 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
373 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
374 return meta; \
375 }
376 GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_META)
377 #undef DECLARE_GATE_META
378
379 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
380 const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \
381 { \
382 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, value); \
383 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
384 return meta; \
385 }
386 GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_META)
387 #undef DECLARE_GATE_META
388
389 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
390 const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset) \
391 { \
392 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, value, pcOffset); \
393 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
394 return meta; \
395 }
396 GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
397 #undef DECLARE_GATE_META
398
399 #define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V) \
400 const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset, bool noGC) \
401 { \
402 auto meta = new (chunk_) TypedCallMetaData(OpCode::OP, R, S, D, value, pcOffset, noGC); \
403 meta->SetKind(GateMetaData::Kind::TYPED_CALL); \
404 return meta; \
405 }
406 GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL)
407 #undef DECLARE_GATE_META_FOR_CALL
408
409 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
410 const GateMetaData* GateMetaBuilder::NAME(uint64_t pcOffset) const \
411 { \
412 auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, pcOffset); \
413 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
414 return meta; \
415 }
416 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
417 #undef DECLARE_GATE_META
418
419 const GateMetaData* GateMetaBuilder::Arg(uint64_t value)
420 {
421 switch (value) {
422 #define DECLARE_CACHED_VALUE_CASE(VALUE) \
423 case VALUE: { \
424 return &cache_.cachedArg##VALUE##_; \
425 }
426 CACHED_ARG_LIST(DECLARE_CACHED_VALUE_CASE)
427 #undef DECLARE_CACHED_VALUE_CASE
428 default:
429 break;
430 }
431
432 auto meta = new (chunk_) OneParameterMetaData(OpCode::ARG, GateFlags::HAS_ROOT, 0, 0, 0, value);
433 meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER);
434 return meta;
435 }
436 } // namespace panda::ecmascript::kungfu
437