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