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