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